Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Foldable vs Traversable

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?

like image 250
FtheBuilder Avatar asked Mar 08 '16 02:03

FtheBuilder


People also ask

What is the traversable Typeclass used for?

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.

What does foldable mean Haskell?

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.


1 Answers

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.

like image 199
sclv Avatar answered Sep 28 '22 13:09

sclv