Is difference between foldl
and foldr
just the direction of looping? I thought there was a difference in what they did, not just in the direction?
Difference Between foldl and foldr The difference is that foldl is tail-recursive, whereas foldr is not. With foldr and non-optimized patterns, proc is applied to the current value and the result of recursing on the rest of the list. That is, evaluation cannot complete until the entire list has been traversed.
Only foldr is lazy and can be used for codata/infinite streams. While foldl is tail-recursive (enhanced with strict application foldl' can avoid stack overflow). This is why foldr should be used by default in Haskellin order preserve laziness across function composition.
In functional programming, fold (or reduce) is a family of higher order functions that process a data structure in some order and build a return value. This is as opposed to the family of unfold functions which take a starting value and apply it to a function to generate a data structure.
From HaskellWiki. The foldr function applies a function against an accumulator and each value of a Foldable structure from right to left, folding it to a single value. foldr is a method of the Foldable typeclass: foldr (++) [] [[0, 1], [2, 3], [4, 5]] -- returns [0, 1, 2, 3, 4, 5]
There's a difference if your function isn't associative (i.e. it matters which way you bracket expressions) so for example,foldr (-) 0 [1..10] = -5
but foldl (-) 0 [1..10] = -55
.
This is because the former is equal to 1-(2-(3-(4-(5-(6-(7-(8-(9-(10 - 0)))))))))
, whereas the latter is (((((((((0-1)-2)-3)-4)-5)-6)-7)-8)-9)-10
.
Whereas because (+)
is associative (doesn't matter what order you add subexpressions),foldr (+) 0 [1..10] = 55
and foldl (+) 0 [1..10] = 55
. (++)
is another associative operation because xs ++ (ys ++ zs)
gives the same answer as (xs ++ ys) ++ zs
(although the first one is faster - don't use foldl (++)
).
Some functions only work one way:foldr (:) :: [a] -> [a] -> [a]
but foldl (:)
is nonsense.
Have a look at Cale Gibbard's diagrams (from the wikipedia article); you can see f
getting called with genuinely different pairs of data:
Another difference is that because it matches the structure of the list, foldr
is often more efficient for lazy evaluation, so can be used with an infinite list as long as f
is non-strict in its second argument (like (:)
or (++)
). foldl
is only rarely the better choice. If you're using foldl
it's usually worth using foldl'
because it's strict and stops you building up a long list of intermediate results. (More on this topic in the answers to this question.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With