>>> fold [[1, 2, 3], [4, 5], [6], []] [1,2,3,4,5,6]
>>> fold $ Node (Leaf (Sum 1)) (Sum 3) (Leaf (Sum 5)) Sum {getSum = 9}Folds of unbounded structures do not terminate when the monoid's (<>) operator is strict:
>>> fold (repeat Nothing) * Hangs forever *Lazy corecursive folds of unbounded structures are fine:
>>> take 12 $ fold $ map (\i -> [i..i+2]) [0..] [0,1,2,1,2,3,2,3,4,3,4,5] >>> sum $ take 4000000 $ fold $ map (\i -> [i..i+2]) [0..] 2666668666666
>>> foldMap Sum [1, 3, 5] Sum {getSum = 9}
>>> foldMap Product [1, 3, 5] Product {getProduct = 15}
>>> foldMap (replicate 3) [1, 2, 3] [1,1,1,2,2,2,3,3,3]When a Monoid's (<>) is lazy in its second argument, foldMap can return a result even from an unbounded structure. For example, lazy accumulation enables Data.ByteString.Builder to efficiently serialise large data structures and produce the output incrementally:
>>> import qualified Data.ByteString.Lazy as L >>> import qualified Data.ByteString.Builder as B >>> let bld :: Int -> B.Builder; bld i = B.intDec i <> B.word8 0x20 >>> let lbs = B.toLazyByteString $ foldMap bld [0..] >>> L.take 64 lbs "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24"
foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xnNote that to produce the outermost application of the operator the entire input list must be traversed. Like all left-associative folds, foldl will diverge if given an infinite list. If you want an efficient strict left-fold, you probably want to use foldl' instead of foldl. The reason for this is that the latter does not force the inner results (e.g. z `f` x1 in the above example) before applying them to the operator (e.g. to (`f` x2)). This results in a thunk chain O(n) elements long, which then must be evaluated from the outside-in. For a general Foldable structure this should be semantically identical to:
foldl f z = foldl f z . toList
>>> foldl (+) 42 [1,2,3,4] 52Though the result below is lazy, the input is reversed before prepending it to the initial accumulator, so corecursion begins only after traversing the entire input string.
>>> foldl (\acc c -> c : acc) "abcd" "efgh" "hgfeabcd"A left fold of a structure that is infinite on the right cannot terminate, even when for any finite input the fold just returns the initial accumulator:
>>> foldl (\a _ -> a) 0 $ repeat 1 * Hangs forever *WARNING: When it comes to lists, you always want to use either foldl' or foldr instead.
foldl' f z = foldl' f z . toList
foldlM f z t = do aa <- f z a bb <- f aa b ... xx <- f ww x yy <- f xx y return yy -- Just @return z@ when the structure is emptyFor a Monad m, given two functions f1 :: a -> m b and f2 :: b -> m c, their Kleisli composition (f1 >=> f2) :: a -> m c is defined by:
(f1 >=> f2) a = f1 a >>= f2Another way of thinking about foldlM is that it amounts to an application to z of a Kleisli composition:
foldlM f z t = flip f a >=> flip f b >=> ... >=> flip f x >=> flip f y $ zThe monadic effects of foldlM are sequenced from left to right. If at some step the bind operator (>>=) short-circuits (as with, e.g., mzero in a MonadPlus), the evaluated effects will be from an initial segment of the element sequence. If you want to evaluate the monadic effects in right-to-left order, or perhaps be able to short-circuit after processing a tail of the sequence of elements, you'll need to use foldrM instead. If the monadic effects don't short-circuit, the outermost application of f is to the rightmost element y, so that, ignoring effects, the result looks like a left fold:
((((z `f` a) `f` b) ... `f` w) `f` x) `f` y
>>> let f a e = do { print e ; return $ e : a } >>> foldlM f [] [0..3] 0 1 2 3 [3,2,1,0]
foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...)Note that since the head of the resulting expression is produced by an application of the operator to the first element of the list, given an operator lazy in its right argument, foldr can produce a terminating expression from an unbounded list. For a general Foldable structure this should be semantically identical to,
foldr f z = foldr f z . toList
>>> foldr (||) False [False, True, False] True
>>> foldr (||) False [] False
>>> foldr (\c acc -> acc ++ [c]) "foo" ['a', 'b', 'c', 'd'] "foodcba"
>>> foldr (||) False (True : repeat False) TrueBut the following doesn't terminate:
>>> foldr (||) False (repeat False ++ [True]) * Hangs forever *
>>> take 5 $ foldr (\i acc -> i : fmap (+3) acc) [] (repeat 1) [1,4,7,10,13]
foldrM f z t = do yy <- f y z xx <- f x yy ... bb <- f b cc aa <- f a bb return aa -- Just @return z@ when the structure is emptyFor a Monad m, given two functions f1 :: a -> m b and f2 :: b -> m c, their Kleisli composition (f1 >=> f2) :: a -> m c is defined by:
(f1 >=> f2) a = f1 a >>= f2Another way of thinking about foldrM is that it amounts to an application to z of a Kleisli composition:
foldrM f z t = f y >=> f x >=> ... >=> f b >=> f a $ zThe monadic effects of foldrM are sequenced from right to left, and e.g. folds of infinite lists will diverge. If at some step the bind operator (>>=) short-circuits (as with, e.g., mzero in a MonadPlus), the evaluated effects will be from a tail of the element sequence. If you want to evaluate the monadic effects in left-to-right order, or perhaps be able to short-circuit after an initial sequence of elements, you'll need to use foldlM instead. If the monadic effects don't short-circuit, the outermost application of f is to the leftmost element a, so that, ignoring effects, the result looks like a right fold:
a `f` (b `f` (c `f` (... (x `f` (y `f` z))))).
>>> let f i acc = do { print i ; return $ i : acc } >>> foldrM f [] [0..3] 3 2 1 0 [0,1,2,3]
foldM f a1 [x1, x2, ..., xm] == do a2 <- f a1 x1 a3 <- f a2 x2 ... f am xmIf right-to-left evaluation is required, the input list should be reversed. Note: foldM is the same as foldlM
foldl1 f = foldl1 f . toList
>>> foldl1 (+) [1..4] 10
>>> foldl1 (+) [] *** Exception: Prelude.foldl1: empty list
>>> foldl1 (+) Nothing *** Exception: foldl1: empty structure
>>> foldl1 (-) [1..4] -8
>>> foldl1 (&&) [True, False, True, True] False
>>> foldl1 (||) [False, False, True, True] True
>>> foldl1 (+) [1..] * Hangs forever *
>>> foldr1 (+) [1..4] 10
>>> foldr1 (+) [] Exception: Prelude.foldr1: empty list
>>> foldr1 (+) Nothing *** Exception: foldr1: empty structure
>>> foldr1 (-) [1..4] -2
>>> foldr1 (&&) [True, False, True, True] False
>>> foldr1 (||) [False, False, True, True] True
>>> foldr1 (+) [1..] * Hangs forever *
{-# LANGUAGE DeriveFoldable #-} data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a) deriving FoldableA more detailed description can be found in the Overview section of Data.Foldable#overview. For the class laws see the Laws section of Data.Foldable#laws.
iterate f == unfoldr (\x -> Just (x, f x))In some cases, unfoldr can undo a foldr operation:
unfoldr f' (foldr f z xs) == xsif the following holds:
f' (f x y) = Just (x,y) f' z = Nothing
>>> take 1 (unfoldr (\x -> Just (x, undefined)) 'a') "a"
>>> unfoldr (\b -> if b == 0 then Nothing else Just (b, b-1)) 10 [10,9,8,7,6,5,4,3,2,1]
>>> take 10 $ unfoldr (\(x, y) -> Just (x, (y, x + y))) (0, 1) [0,1,1,2,3,5,8,13,21,54]