This week, let’s talk about Haskell. I has been learning Haskell in my free time for a while and i am really enjoy it. I recommend everybody to learn it, whether you can use it for your day job or not, because it will give you a very different view and way of thinking to improve your programming skills.

Let’s start with a very simple problem likes this: given a user id, we want to find all posts of that user.

```
type Post = String
type UserId = String
data User = User { _userId :: UserId }
findUser :: String -> IO (Maybe User)
findUser = undefined
findPost :: User -> IO (Maybe [Post])
findPost = undefined
getPosts :: UserId -> IO (Maybe [Post])
getPosts userId = do
maybeUser <- findUser userId
case maybeUser of
Just user -> findPost user
Nothing -> return Nothing
```

First, we find the user by calling `findUser`

. If we find the user, we will call `findPost`

to get all posts of that user. Notice the implementation of `getPosts`

, we need to unwrap `Maybe`

, pattern match on it.

*In case you are new to Haskell, IO is the monad that allows you do IO side effect in Haskell, read file, print to console, make network, api call. Maybe is another monad to represent computation that might go wrong by not returning a value. So when you see Maybe User, it means this function may return a user, may be not. That’s why we need to check if the Maybe value is Just or Nothing. And IO (Maybe User) means this function will make some IO call to outside, can read a file, query database and returns a Maybe User.*

Let’s have another example to see the problem more clearly. Now we has another requirement, only friends can see all posts of each other. So we need to check friend relationship before return all posts.

```
isFriend :: User -> User -> IO (Maybe Bool)
isFriend = undefined
getFriendPosts :: UserId -> UserId -> IO (Maybe [Post])
getFriendPosts userId friendId = do
maybeUser <- findUser userId
case maybeUser of
Just user -> do
maybeFriendUser <- findUser friendId
case maybeFriendUser of
Just friendUser -> do
maybeIsFriend <- getRelationShip user friendUser
case maybeIsFriend of
-- I really want to give up this blog post at this point.
Just isFriend -> do
if isFriend
then
getPosts friendId
else
return Nothing
Nothing -> return Nothing
Nothing -> return Nothing
Nothing -> return Nothing
```

Now, the code looks really ugly now. We have a deep nested code, each step we need to manual unwrap `Maybe`

value, process if it has value, otherwise return `Nothing`

. This looks really bad not only because of nested steps, but also because we can’t leverage `Maybe`

monad feature.

Let’s recall the `Monad`

instance of `Maybe`

and `IO`

.

```
instance Monad Maybe where
Nothing >>= f = Nothing
Just x >> f = f x
-- This is not the real implementation of IO monad but you can get the idea
instance Monad IO where
(action1 >>= action2) world0 =
let (a, world1) = action1 world0
(b, world2) = action2 a world1
in (b, world2)
```

In `Maybe`

monad, the computation chains will stop when `Nothing`

is returned from any computation, so `Nothing >>= f`

will return `Nothing`

. In `IO`

monad, it will run each computation sequencely. So if we mix them together, our `IO Maybe`

mond which behave like `IO`

normal monad. But in this case, we want our `IO Maybe`

to also have behaviour of `Maybe`

monad. If any computation returns `Nothing`

, it should stop and return `Nothing`

.

`do`

notation is a syntax sugar in haskell

*is*

So the main problem here is we use two monad `IO`

and `Maybe`

together, and right now they don’t work well with each other. We only use feature of `IO`

monad and not `Maybe`

monad. To illustrate the idea, here is what will happens if we write our code with only `Maybe`

monad.

```
type Post = String
type UserId = String
data User = User { _userId :: UserId }
findUser :: String -> Maybe User
findUser = undefined
findPost :: User -> Maybe [Post]
findPost = undefined
getPosts :: UserId -> Maybe [Post]
getPosts userId = do
user <- findUser userId
findPost user
isFriend :: User -> User -> Maybe Bool
isFriend = undefined
getFriendPosts :: UserId -> UserId -> Maybe [Post]
getFriendPosts userId friendId = do
user <- findUser userId
friend <- findUser friendId
friendCheck <- isFriend user friend
if friendCheck
then
getPosts friendId
else
Nothing
```

It looks nicer, right? We don’t need to check for `Just`

and `Nothing`

at every step, we depend on the monad instance of `Maybe`

to take care of it.

If only we can make our `IO Maybe`

behave like both `IO`

, which can make IO call to outside world, and `Maybe`

, represent a computation may return nothing and stop as soon as one function returns `Nothing`

, we will be able to make the code above less verbose and more expressive. Let’s try to create that new monad together, we will call it `MaybeIO`

monad.

```
newtype MaybeIO a = MaybeIO { runMaybeIO :: IO(Maybe a) }
findUser :: String -> MaybeIO User
findUser = undefined
findPost :: User -> MaybeIO [Post]
findPost = undefined
isFriend :: User -> User -> MaybeIO Bool
isFriend = undefined
```

Now before we rewrite `getFriendPosts`

, we need to provide monad instance for our `MaybeIO`

.

```
instance Functor MaybeIO where
fmap f = MaybeIO . fmap (fmap f) . runMaybeIO
instance Applicative MaybeIO where
pure a = MaybeIO $ return (Just a)
f <*> a = MaybeIO $ (<*>) <$> (runMaybeIO f) <*> (runMaybeIO a)
instance Monad MaybeIO where
return a = MaybeIO $ return (Just a)
x >>= f = MaybeIO $ runMaybeIO x >>= \a -> case a of
Just value -> runMaybeIO $ f value
Nothing -> return Nothing
```

Basically remember our `MaybeIO`

is actually `IO Maybe`

, so we write our new monad based on functionality of these two. For the `(>>=)`

function, we called `runMaybeIO x`

, which return us a `IO Maybe`

. Then we use `(>>=)`

instance of `IO`

to get back a, which is `Maybe`

monad.

If you confuse because of `runMaybeIO`

and `MaybeIO`

constructor, here are their signatures:

We use them to convert between our new `MaybeIO`

monad and the original `IO Maybe`

.

Now it’s time to rewrite our `getFriendPosts`

```
getFriendPosts :: UserId -> UserId -> MaybeIO [Post]
getFriendPosts userId friendId = do
user <- findUser' userId
friend <- findUser' friendId
friendCheck <- isFriend' user friend
if friendCheck
then
getPosts' friendId
else
return mempty
```

It looks like the example with `Maybe`

monad above, right? We’ve just combined `IO`

and `Maybe`

together into a single monad, which behave like `Maybe`

and have `IO`

capability. If we go one step further, generalize it, instead of `MaybeIO`

, we want to use `Maybe`

with any other monad, add `Maybe`

behaviour to it.

```
newtype MaybeT m a = MaybeT { runMaybeT :: m(Maybe a) }
instance Monad m => Functor (MaybeT m) where
fmap f = MaybeT . fmap (fmap f) . runMaybeT
instance Monad m => Applicative (MaybeT m) where
pure a = MaybeT $ return (Just a)
f <*> a = MaybeT $ (<*>) <$> (runMaybeT f) <*> (runMaybeT a)
instance Monad m => Monad (MaybeT m) where
return a = MaybeT $ return (Just a)
x >>= f = MaybeT $ runMaybeT x >>= \a -> case a of
Just value -> runMaybeT $ f value
Nothing -> return Nothing
```

Instead of `MaybeIO`

, we have `MaybeT m`

with m is another monad such as `IO`

. Our `MaybeIO`

above become `MaybeT IO`

. We have finished written our first Monad Transformer, MaybeT.

Monad Transformer allows us to stack multiple monads together and behave likes one single monad, combined all functionalities of these monads inside the stack. For example, if we want to build a real application, we need to read global config (`Reader`

monad), write log (`Writer`

monad), store application state (`State`

monad), handling exception (`Either`

monad), and of course `IO`

monad. We can write a `ReaderT AppConfig (WriterT String (StateT AppState (ExceptT String IO)))`

monad to represent our application and reuse all functionality of these monads.

That’s all for this post. We saw two real world problems. We learn to write a custom `MaybeIO`

monad which combined `Maybe`

and `IO`

together to solve the problem. After that we generalize it into `MaybeT`

monad transformer and learn how monad transformer can help us in real application by stack multiple monad together.

Next time, we will look at `mtl`

and `transformers`

, two monad transformer libraries in Haskell ecosystem, which provide us the transformer version of all standard monads so we don’t need to write our own. We will also look at the order of the monad in the stack and how it will effect behaviour of the whole stack.

Thank you.

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.