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:
>>> 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:
>>> 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.