Consider one of these implementations of a function to remove consecutive duplicates from a list:
uniq :: Eq a => [a] -> [a]
uniq [] = []
uniq (x:xs) = x:uniq (dropWhile (x ==) xs)
uniq :: Eq a => [a] -> [a]
uniq (x:xs@(y:_))
| x == y = x:tail (uniq xs)
| otherwise = x:uniq xs
uniq l = l
They both work as expected on both finite and infinite lists. To be more specific, for infinite lists, I expect take n $ uniq l
to terminate as long as there are no infinitely long sequences of duplicate values before there are n
values to return.
Now consider this attempt at such a function, using foldr
:
uniq :: (Foldable t, Eq a) => t a -> [a]
uniq = foldr uniqHelper []
where uniqHelper x [] = [x]
uniqHelper x acc@(y:_)
| x == y = acc
| otherwise = x:acc
This works correctly on finite lists, but never terminates for infinite ones, because uniqHelper
always needs to evaluate its second argument. Is this something that can be fixed with a more clever uniqHelper
, or is it inherently impossible to use folding for this task?