7

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...

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Madderote
  • 1,107
  • 10
  • 19
  • define `(<<$>>) = fmap . fmap`, then use `(+1) <<$>> [Just 1, Just 2, Just 3]`. also, `(<<<$>>>) = fmap . fmap . fmap` for `(+1) <<<$>>> Right [Just 1, Just 2, Just 3]` etc. – Will Ness Nov 02 '18 at 17:01

1 Answers1

9

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 Functors, like lists, Maybes, 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) Functors 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.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • 6
    There is also `(+1) <$> Compose [Just 1, Just 2]`. But in every real-life case I've come across, it's been way syntactically heavier to bring in `Compose` than to just type `fmap` twice, so... +1 on this answer from me. =) – Daniel Wagner Nov 01 '18 at 15:27
  • @DanielWagner: thanks. Did not know about the `Compose`, added to the answer. – Willem Van Onsem Nov 01 '18 at 15:33