<div dir="ltr"><div><div><div><div><div><div><div><div><span style="font-family:arial,helvetica,sans-serif">Currently, isSuffixOf is defined like this:<br><br>xs `isSuffixOf` ys = reverse xs `isPrefixOf` reverse ys<br><br>If ys is much longer than xs, this is not so wonderful, because we have to reverse the whole spine of ys. It also will fail whenever either xs *or* ys is infinite. The following implementation seems a lot saner (although longer):<br><br>isSuffixOf              :: forall a . (Eq a) => [a] -> [a] -> Bool<br>[]     `isSuffixOf` _   =  True<br>needle `isSuffixOf` hay =<br>      maybe False<br>            (\fp -> needle `eq` getEndChunk hay fp)<br>            (getFrontPointer needle hay)<br>  where<br></span></div><div><span style="font-family:arial,helvetica,sans-serif">    eq :: [a] -> [a] -> [a]<br></span></div><div><span style="font-family:arial,helvetica,sans-serif">    (x:xs) `eq` (y:ys) = x==y && (xs `eq` ys)<br><br></span></div><div><span style="font-family:arial,helvetica,sans-serif">    getEndChunk :: [a] -> [a] -> [a]<br></span></div><div><span style="font-family:arial,helvetica,sans-serif">    getEndChunk (_:hy) (_:fp) = getEndChunk hy fp<br>    getEndChunk hy     _      = hy<br><br>    getFrontPointer :: [a] -> [a] -> Maybe [a]<br>    getFrontPointer [] hy         = Just hy<br>    getFrontPointer _  []         = Nothing<br>    getFrontPointer (_:nd) (_:hy) = getFrontPointer nd hy<span class=""></span><span class=""></span><br><br>This doesn't do any of that crazy stuff, and it will work just fine if the needle is infinite. The only slightly sticky point is that it's not *strictly* lazier. In particular,<br><br></span></div><span style="font-family:arial,helvetica,sans-serif">[1,2] `Data.List.isSuffixOf` [undefined, 7] = False<br></span></div><span style="font-family:arial,helvetica,sans-serif">[1,2] `isSuffixOf` [undefined, 7] = undefined<br><br></span></div><span style="font-family:arial,helvetica,sans-serif">But note that<br><br></span></div><span style="font-family:arial,helvetica,sans-serif">[1,2] `Data.List.isSuffixOf` [7,undefined] = undefined<br></span></div><span style="font-family:arial,helvetica,sans-serif">[1,2] `isSuffixOf` [7, undefined] = False<br><br></span></div><span style="font-family:arial,helvetica,sans-serif">It would be possible to get the same kind of laziness at the end using something structured as above, but it requires some unpleasantness: instead of using<br><br>needle `eq` getEndChunk hay fp<br><br></span></div><span style="font-family:arial,helvetica,sans-serif">we'd have to use<br><br>needle `backwardsEq` getEndChunk hay fp<br><br>(x:xs) `backwardsEq` (y:ys) = (xs `backwardsEq` ys) && x==y<br><br></span></div><div><span style="font-family:arial,helvetica,sans-serif">This is yucky. My guess is that no one is relying on the current behavior, but I'd like to make sure everyone's okay with this.<br><br></span></div><div><span style="font-family:arial,helvetica,sans-serif">David<br></span></div></div>