(Not updated very recently)
class Foldable_ t where
foldr :: (a -> b -> b) -> b -> t a -> b
foldMap :: Monoid m => (a -> m) -> t a -> m
fold :: Monoid m => t m -> m
...
Minimal complete definition is foldr
or
foldMap
. Why can’t fold
possibly be a minimal
complete definition? Because it doesn’t work for all
t a
, only those where a
is a
Monoid
.
Default definitions:
foldMap =
foldr (\a acc -> f a <> acc) mempty
foldr f b ta =
appEndo (foldMap (\a -> Endo (f a)) ta) b
fold =
foldMap id
Data.Foldable
, exposed by Prelude
, contains
additional members.
data Tree a
= Empty
| Node (Tree a) a (Tree a)
instance Foldable_ Tree where
-- foldMap :: Monoid m => (a -> m) -> Tree a -> m
foldMap f Empty = mempty
foldMap f (Node l a r) = foldMap f l <> f a <> foldMap f r
If Tree
is a Functor
…
instance Functor Tree where
-- fmap :: (a -> b) -> Tree a -> Tree b
fmap f Empty = Empty
fmap f (Node l a r) = Node (fmap f l) (f a) (fmap f r)
… then the Foldable
can be written yet more concisely
via fold
:
instance Foldable_ Tree where
-- foldMap :: Monoid m => (a -> m) -> Tree a -> m
foldMap f = fold . fmap f -- boilerplate definition with two passes
-- fold :: Monoid m => Tree m -> m
fold Empty = mempty
fold (Node l a r) = fold l <> a <> fold r
Many types which are both Functor
s and
Foldable
s have even more in common…