I'd say its easier to implement takeWhile using foldr:
takeWhile p = foldr (\x xs -> if p x then x : xs else []) []
Also, foldr most definitely does not consume the whole list before producing a result. Take this definition:
foldr :: (a -> b -> b) -> b -> [a] -> b foldr f z [] = z foldr f z (x:xs) = f x (foldr f z xs)
As you can see in the cons case; foldr calls
f with
x and the result of a recursive call.
However, since Haskell is lazy,
f gets executed
before the result of the recursive call is computed. If
f decides to never inspects its second argument, the recursive call will never be evaluated. So that's why you can do:
takeWhile (<4) [0..]
However, you are right about foldl.
foldl :: (a -> b -> a) -> a -> [b] -> a foldl f z [] = z foldl f z (x:xs) = foldl (f z x) xs
foldl first recurses, before executing the
f function that produces the result value.
So calling the takeWhile', defined below, with an infinite list will result in an infinite computation.
takeWhile' p = foldl (\ys x -> if p x then ys ++ [x] else ys) []