Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

map Functor over a list in Haskell

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

like image 819
Madderote Avatar asked Nov 01 '18 15:11

Madderote


People also ask

Is list a functor?

Functor is a type class that abstracts over type constructors that can be map 'ed over. Examples of such type constructors are List , Option , and Future .

Is map a functor?

yes map is a functor.

How do I map a function in Haskell?

Whenever we want to apply a function on each element of a given list and produce a new list consisting of the updated elements, then we make use of a function called map() function in Haskell and this map() function takes a list and the function to be applied on each element in the list as an input and returns a new ...

Is Fmap a functor?

The expression fmap (*2) is a function that takes a functor f over numbers and returns a functor over numbers. That functor can be a list, a Maybe , an Either String, whatever. The expression fmap (replicate 3) will take a functor over any type and return a functor over a list of elements of that type.


1 Answers

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.

like image 144
Willem Van Onsem Avatar answered Sep 25 '22 20:09

Willem Van Onsem