Skip to content

foldMap'

foldMap' :: Monoid m => (a -> m) -> t a -> m`

is a strict version of foldMap that avoids the overheads of laziness and uses left-to-right folding instead of right-to-left folding, which is the behaviour required of foldMap. This is similar to the difference between the strict version of foldl for lists, foldl', compared to foldl and foldr. Note, however, that strictness does not always lead to faster code. In fact, it may make your code run forever where the lazy code would have terminated. In general, do not play around with strict versions of functions until you know that you need them to improve your code's performance.

To beat a dead horse once more, here are two examples that use foldMap' with the Sum and Product monoids:

GHCi
>>> tree = Node Empty 5 (Node (Node Empty 3 Empty) 1 (Node Empty 2 Empty))
>>> getSum $ foldMap' Sum tree
11
>>> getProduct $ foldMap' Product tree
30

These are examples where using foldMap' instead of foldMap is the correct choice. The final result we obtain is a number. Whenever that's the case, it is usually the right choice to use strict evaluation, because it avoids building up a massive expression and evaluates subexpressions immediately.

What wouldn't work too well is using foldMap' with the list monoid. It sure produces the correct result:

GHCi
>>> foldMap' singleton tree
[5,3,1,2]

However, for large trees, this implementation of converting a tree to a list is horribly inefficient. The problem is less the strict evaluation but the fact that foldMap' implements a left-to-right fold. This means that we append each tree element to the end of the list we're constructing. Appending to the end of a list takes linear time in the size of the list to which we're appending. Thus, foldMap' singleton tree takes quadratic time in the number of elements in the tree. A right-to-left fold takes linear time.