(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 Functors and
Foldables have even more in common…