Reputation: 1137
bit confused. fmap
sounds like it can map
all over a list of Maybe
's, but I can't get it to work if I use e.g. fApplyFunctor = (+1) <$> [Just 1, Just 2]
.
What seems to work perfectly fine is: map ((+1) <$>) [Just 1, Just 2, Just 3]
. This seems to be overkill in that sense that I recall fmap
could do that by itself already...
Upvotes: 7
Views: 856
Reputation: 477533
No fmap
means you can map over an arbitrary Functor
type (well think about it for now as a collection), but you only do this one "functor level" deep. In case you fmap
with a list, it is exactly equivalent to map
.
fmap
however is defined over all sorts of Functor
s, like lists, Maybe
s, etc. Here you can thus fmap
in the fmap
to map over two levels:
fApplyFunctor = fmap (fmap (+1)) [Just 1, Just 2]
This will then result in:
Prelude> fmap (fmap (+1)) [Just 1, Just 2]
[Just 2,Just 3]
Prelude> (fmap (+1)) <$> [Just 1, Just 2]
[Just 2,Just 3]
Prelude> ((+1) <$>) <$> [Just 1, Just 2]
[Just 2,Just 3]
EDIT: like @DanielWagner says, there exists a data type Compose
which works over two (or more if you cascade) Functor
s and thus allows us to fmap
two levels deep. This is implemented like:
newtype Compose f g a = Compose { getCompose :: f (g a) } instance (Functor f, Functor g) => Functor (Compose f g) where fmap f (Compose x) = Compose (fmap (fmap f) x)
so here we again perform an fmap
on two levels:
Prelude Data.Functor.Compose> getCompose ((+1) <$> Compose [Just 1, Just 2])
[Just 2,Just 3]
But as you see it requires some syntax to first wrap the data in a Compose
, and then to later "unwrap" it out of the Compose
, so this requires some extra work as well.
Upvotes: 9