# Functors Compose, Monads Do Not

## Functor Composition

Let’s start with a refresher of `map`

:

`map :: forall a b. (a -> b) -> f a -> f b`

In other words, map takes a function `a -> b`

and gives us a function `f a -> f b`

. For that reason, we can take any two nested functors (e.g. `Array`

and `Maybe`

) and run a function on the nested values by putting two `map`

s together:

```
v :: Array (Maybe Int)
= [Just 1, Nothing, Just 3]
v
f1 :: Int -> String
= show
f1
main :: Effect Unit
= do
main $ map (map f1) v
logShow
-- [(Just "1"),Nothing,(Just "3")]
```

## Monad Composition

This time we want to take a look at `bind`

:

`bind :: forall a b. m a -> (a -> m b) -> m b`

If we tried to compose the same way we did with functors, we would notice the code does not compile:

```
v :: Array (Maybe Int)
= [Just 1, Nothing, Just 3]
v
f2 :: Int -> Array (Maybe String)
= [Just $ show i]
f2 i
main :: Effect Unit
= do
main $ bind v (\x -> bind x f2) -- DOES NOT COMPILE!! logShow
```

The problem here is in the nested `bind`

:

```
-> bind x f2)
bind v (\x ^ Maybe Int
^ Int -> Array (Maybe String)
```

In fact, `Maybe Int -> (Int -> Array (Maybe String)) -> ??`

is not what `bind`

expects: the first argument seems to indicate that `m`

is `Maybe`

but the second seems to indicate that `m`

is `Array`

. This does not compile since the monad `m`

is supposed to be the same.

To make the program compile we have to make use of a function (i.e. `maybe`

) specific to the monad we are dealing with (i.e. `Maybe`

):

```
main :: Effect Unit
= do
main -- logShow $ bind v (\x -> bind x f2) -- DOES NOT COMPILE!!
$ bind v (maybe (pure Nothing) f2) logShow
```

Or we could use the `MaybeT`

monad transformer:

```
v2 :: MaybeT Array Int
= MaybeT [Just 1, Nothing, Just 3]
v2
f3 :: Int -> MaybeT Array String
= MaybeT [Just $ show i]
f3 i
main :: Effect Unit
= do
main --logShow $ bind v (\x -> bind x f2)
$ bind v (maybe [Nothing] f2)
logShow $ runMaybeT $ bind v2 f3 logShow
```

## Outro

I’ve blatantly copied the content of this blog post out of a talk by Tony Morris. So be sure to check the original stuff out!

If you liked the post and want to help spread the word, please make some noise 🤘 But only if you really liked it. Otherwise, please feel free to comment or tweet me with any suggestions or feedback. And please do cause I need help with my FP!