＊In the previous article, "Understanding Functor, Applicative, and Monad" we summarized the characteristics of each, and in this article we will look at how to utilize them with specific examples. The use of Monad and other tools facilitates error handling and makes the program more resistant to specification changes.

Author : Kenta Inoue

# Introduction

In the last issue, we looked at the characteristics of `Functor`

,
`Applicative`

, and
`Monad`

. The following is a summary of them.

`Functor m`

: Create`m A -> m B`

from`A -> B`

.`Applicative m`

: Create`m A -> m B -> m C`

from`A -> B -> C`

`Monad m`

: Create`m A -> m B`

from`A -> m B`

. (for any type`A,`

`B`

,`C`

respectively)

This article will look at these applications.

# Easier error handling

First, consider the following potentially error-prone functions

```
mdiv :: Integral a => a -> a -> Maybe a
mdiv x y =
if y == 0
then Nothing
else Just $ x `div` y
```

`mdiv`

is just a quotient operation, but the return value is of type
`Maybe`

, which returns
`Nothing`

when divided by `0`

.

```
main = do
print $ 10 `mdiv` 2 -- Just 5
print $ 10 `mdiv` 0 -- Nothing
```

If you want to process a value that may be an error (for example, if you want to find a value that is five times this value), you cannot process it as it is, and you must separate the case by whether or not it is an error.

```
-- print $ 5 * (10 `mdiv` 2) -- error
print $ case (10 `mdiv` 2) of
Nothing -> Nothing
Just x -> Just (5 * x)
```

However, this becomes tedious when processing increases, and also makes readability worse.
So, let's rewrite it
using the `Functor`

operator `<$>`

.

Now, in `Functor Maybe`

, the operator `<$>`

has type
`(a -> b) -> Maybe a -> Maybe b`

, so

```
-- print $ 5 * (10 `mdiv` 2) -- error
print $ (5 *) <$> (10 `mdiv` 2) -- Just 25
```

The same process as above can be performed by writing.

Similarly, `Applicative`

and `Monad`

operations can be used as follows.

```
import GHC.Base(liftA2)
main = do
-- print $ (10 `mdiv` 2) * (10 `mdiv` 5) -- error
print $ (*) <$> (10 `mdiv` 2) <*> (10 `mdiv` 5) -- Just 10
print $ liftA2 (*) (10 `mdiv` 2) (10 `mdiv` 5) -- Just 10
-- print $ 10 `mdiv` 2 `mdiv` 5 -- error
print $ (10 `mdiv` 2) >>= (`mdiv` 5) -- Just 1
-- (<*>) :: Applcative m => m (a -> b) -> m a -> m b
-- liftA2 :: Applicative m => (a -> b -> c) -> m a -> m b -> m c
-- (>>=) :: Monad m => m a -> (a -> m b) -> m b
```

# Easier to change specifications

The `mdiv`

mentioned earlier was a function that returned the type `Maybe`

, as we will
recapitulate.

```
mdiv :: Integral a => a -> a -> Maybe a
mdiv x y =
if y == 0
then Nothing
else Just $ x `div` y
```

However, if there are other processes that may generate errors, the `Maybe`

type
will return only
`Nothing`

when an error occurs, and it will be difficult to tell where the error occurred. Therefore,
to display the error statement, the specification is changed to the `Either String`

type as shown
below instead of the Maybe type.

```
mdiv :: Integral a => a -> a -> Either String a
mdiv x y =
if y == 0
then Left "Error: divided by zero"
else Right $ x `div` y
```

In the past, this change would require a major rewriting of the source code, but if the
processing uses only
operations such as `Monad`

, as in the previous program, the program can be passed without any
changes.

```
main = do
print $ (5 *) <$> (10 `mdiv` 2) -- Right 25
print $ (*) <$> (10 `mdiv` 2) <*> (10 `mdiv` 5) -- Right 10
print $ (10 `mdiv` 2) >>= (`mdiv` 5) -- Right 1
```

By writing in this manner in the form of `Monad`

, even if there are later changes
to the
specifications, major rewrites can be prevented as long as the processing as `Monad`

is the same.

# Applications

Consider a program that performs database processing. First, `import`

database-related libraries.

```
import Control.Monad.Reader(ReaderT,liftIO)
-- Library for database processing.
import Database.Persistent
import Database.Persistent.Sqlite
import Database.Persistent.TH
```

Suppose we have `data1::MyData`

of type `MyData`

that can be stored in a certain
database. Let us consider a function `dbOperation::DBIO ()`

that registers this `data1`

to the
database and retrieves and displays the data as it is now registered. (`DBIO`

is a certain
`Monad`

).

Since it connects to an external database, error handling is essential to the implementation
of this function,
but in practice it can be easily defined as follows using the `Monad`

operation `>>=`

.

```
type DBIO a = ReaderT SqlBackend IO a
dbOperation :: DBIO ()
dbOperation =
insert data1 >>= get >>= liftIO . print
```

We will now look at the function types used for this `dbOperation`

.

```
insert :: (ommited) => val -> m (Key val)
get :: (ommited) => Key val -> m (Maybe val)
print :: Show a => a -> IO ()
class Monad m => MonadIO m where
liftIO :: IO a -> m a
-- (ommited) is a constraint on m and val, but omitted.
-- In this case, m = ReaderT SqlBackend IO, val = MyData.
```

`insert`

registers a variable of any data type `val`

that satisfies
certain constraints in
the database and returns a value of type `m (Key val)`

, where `Key val`

is the ID of the
`val`

data in the database, but may cause errors due to access to an external database, However,
errors can occur due to access to external databases, and it is not always possible to return a variable of type
`key val`

. Therefore, we return `m (Key val)`

wrapped in a certain `Monad`

's
`m`

to handle the error. (You can think of `m`

as `Maybe`

or
`Either`

.) Also, `get`

is a function that receives an ID value of type
`Key val`

, searches the database for that ID value, and returns the result as a
`Maybe val`

, but for the same reason as above, the return value is wrapped in `m`

. The
last function is `print`

, which outputs the data, but it is `liftIO`

to match the type.
Now we can use the operation `>>=`

in `Monad m`

, and
`insert data1 >>= get >>= liftIO . print`

type check passes.

Thus, even functions that actually include error handling for external database connections
can be written easily
and independently of error handling specifications using `Monad`

.

Incidentally, the actual error handling is done internally by the definition of
`Monad m`

, like the
handling of `Nothing`

when `Monad Maybe`

is defined.

### Supplement

above `insert data1 >>= get >>= liftIO . print`

is the following

```
dbOperation :: DBIO ()
dbOperation = do
data1Id <- insert data1
dbdata1 <- get data1Id
liftIO $ print dbdata1
```

It is also possible to write it in a procedural language style, such as

```
deOperation :: DBIO ()
deOperation =
insert data1 >>= (\data1Id -> get data1Id >>= (\dbdata1 -> liftIO (print dbdata1)))
```

shorthand notation. This is consistent with the original program from `Monad`

's third axiom.

# Summary

He described how to utilize `Functor`

, `Applicative`

,
`Monad`

, and others and
their characteristics.