Functors Compose, Monads Do Not
Let’s start with a refresher of
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.
Maybe) and run a function on the nested values by putting two
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")]
This time we want to take a look at
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 x f2) bind v (\x ^ Maybe Int ^ Int -> Array (Maybe String)
Maybe Int -> (Int -> Array (Maybe String)) -> ?? is not what
bind expects: the first argument seems to indicate that
Maybe but the second seems to indicate that
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.
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
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!
Support my work by tweeting this article! 🙏