While studying Applicative
deeper, I came to Traversable
. Although I already knew Foldable
from LYHGG, I haven't seen the former yet, so I started reading the Haskell wiki about Traversable.
While reading it, I understood why Foldable.fold
is parallel to Traversable.sequenceA
and Foldable.foldMap
is parallel to Traversable.traverse
.
I've seen also that every Traversable
is also a Foldable
and a Functor
, and sequenceA
and traversal
have a default implementation in terms of each other:
traverse f = sequenceA . fmap f
sequenceA = traverse id
So, as I have seen in LYHGG that foldMap
is a minimal complete definition for Foldable
, I thought that, it is parallel to traverse
, so fold
(which is parallel to sequenceA
) would be a minimal complete definition too (which it isn't)... Foldable
is not a Functor
like Traversable
is, so we cannot apply this:
foldMap f = fold . fmap f
fold = foldMap id -- this is ok
Why isn't every Foldable
a Functor
, and what would be an instance of Foldable
that actually isn't a Functor
?
Traversable in Haskell unifies the concept of mapping over a container (getting a similary-shaped container in return) with the concept of "internal iterator" that performs an effect for each element.
Haskell, in turn, has two fundamental functions representing reducing, or, as we call it, folding – foldl and foldr – that differ in the order of the folding. foldl reduces elements of a container from left to right (as reduce in other languages usually does), while foldr reduces from right to left.
As dfeuer says, Set
is a good example of a Foldable
that isn't a Functor
.
Consider the type of Set.map
:
map :: Ord b => (a -> b) -> Set a -> Set b
Notice that this is almost fmap
, but it requires an additional Ord b
constraint. Since you have this constraint, it can't be made an instance of Functor
.
Note that Set
is not a functor on Haskell, even with this restriction. Given cleverly set-up Eq
instances we can break the law that fmap f . fmap g === fmap (f . g)
. See this Stack Overflow question for further discussion.
As noted there, Set
is an (endo) functor on the "subcategory of Hask
" with ordered types as sets and with order-preserving maps as morphisms.
So even if it isn't apparent, the fact that we can't make Set
a functor actually hints at a genuine mathematical issue and not just a limitation of our typeclass machinery.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With