fold
The function
fold :: Monoid m => t m -> m
is a specialization of foldMap
to containers whose elements are already values
of some monoidal type m
. Then we don't need to first map the container
elements to the monoid before accumulating the elements. Instead, we can
accumulate the elements in the container directly, using the monoid
multiplication (<>)
. The default implementation uses foldMap
to map every
element to itself, using the identity function id
, and accumulate the
resulting collection of monoid elements:
fold = foldMap id
To try this out, we can exploit that trees are functors, as witnessed by the
following Functor
instance:
>>> :{
| instance Functor Tree where
| fmap f = go
| where
| go Empty = Empty
| go (Node l x r) = Node (go l) (f x) (go r)
| :}
We can now turn our tree
from before, which is a tree of numbers, into a
tree of lists of numbers using fmap singleton tree
. Since the values
stored in this tree are lists, which form a monoid with list concatenation
as the monoid operation, we can collect the elements in the tree into a list
using fold $ fmap singleton tree
:
>>> fold $ fmap singleton tree
[5,3,1,2]
Or we can once again sum or multiply the values in the tree by first using
fmap
to wrap each tree element in a Sum
or Product
, folding the
resulting tree using Sum
or Product
's monoid operation, and then
extracting the value using getSum
or getProduct
:
>>> getSum $ fold $ fmap Sum tree
11
>>> getProduct $ fold $ fmap Product tree
30
Again, these two uses of Sum
and Product
are not the most elegant way to
achieve our goal here, but they serve to illustrate what we can do using fold
.