When trying to implement dropWhile using foldr the first algorithm that I came up with was this
dropWhile' :: (a -> Bool) -> [a] -> [a]
dropWhile' pred = fst . foldr (\cur (acc, xs) ->
if pred cur
then (acc, cur:xs)
else (cur:xs, cur:xs)) ([], [])
While this works, it causes a stack overflow on infinite lists without giving any values. Because I wasn't sure, why this doesn't work, I just played around with the function until I came up with this:
dropWhile' :: (a -> Bool) -> [a] -> [a]
dropWhile' pred = fst . foldr (\cur t -> let (acc, xs) = t in
if pred cur
then (acc, cur:xs)
else (cur:xs, cur:xs)) ([], [])
As you can see, the only difference between this one and the first is, that here I'm destructuring the tuple (acc, xs)
inside a let binding instead of destructuring directly inside the function parameter. For some weird reason, this code works on infinite lists.
If anyone has any idea why this behaves as it does, please let me know.