Code, specifically for web

Functional programming

Some geeky hobbies

# Reader Monad and Function Composition

Let me guess we're about to filter a list of integers, `xs`

.

`xs = [1..100]`

It's not a big deal in Haskell to filter even numbers out.

`filter odd xs`

It's the same when getting only numbers larger than 50.

`filter (> 50) xs`

So far, so good. But what if we want to get numbers which are odd and larger than 50 at the same time? Maybe we should use `&&`

?

`filter (odd && (> 50)) xs`

The code above doesn't work because what we want to `&&`

is the result of the functions, not the functions themselves. The types are mismatched:

```
odd :: Integral a => a -> Bool
(> 50) :: (Ord a, Num a) => a -> Bool
&& :: Bool -> Bool -> Bool
```

Both of the parameters of `&&`

should be `Bool`

, not `a -> Bool`

.

Then, how about the code below? What we want to do is basically something like function composition, so may it work?

`filter (odd . (> 50)) xs`

The answer is, as you may have expected, no. The types are also mismatched too:

```
odd :: Integral a => a -> Bool
(> 50) :: (Ord a, Num a) => a -> Bool
(.) :: (b -> c) -> (a -> b) -> a -> c
```

What we want is actually a function having a type `(a -> Bool) -> (a -> bool) -> a -> Bool`

. Then why not create one?

```
and :: (a -> Bool) -> (a -> Bool) -> a -> Bool
and f g x = (f x) && (g x)
filter (odd `and` (> 50)) xs
```

Easy. We can make it in more general form.

```
lift :: (x -> y -> z) -> (a -> x) -> (a -> y) -> a -> z
lift f g h x = f (g x) (h x)
and = lift (&&)
filter (odd `and` (> 50)) xs
```

Cool! `lift`

actually lifts a function with type `x -> y -> z`

to be applied into other functions! But wait, `lift`

's looking so useful. Why not have it in Haskell by default?

```
import Control.Monad (liftM2)
and = liftM2 (&&)
filter (odd `and` (> 50)) xs
```

Yes, we already have. Haskell is awesome. So, the type of `liftM2`

is `(x -> y -> z) -> (a -> x) -> (a -> y) -> a -> z`

, right?

`liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r`

What? `Monad`

? No, no, no, we've talked about compositing functions, not about monad. Is this article another monad tutorial?

No. I promise it won't be. Monad itself is not what I want to talk about in this article. I still want to talk about function composition. Then, why the heaven is the term `Monad`

coming out in the type of `liftM2`

? Well, in Haskell, function *is* monad. No, more specifically, function *can be* a kind of monad, something called reader monad.

As I promised, I'm not going to explain what is monad. Instead, I'll just show what reader monad looks like.

`instance Monad ((->) x)`

`((->) x)`

is just the prefix form of `x ->`

. Now, let's replace `m`

in the type of `liftM2`

with this, because `x ->`

is an instance of `Monad m`

.

```
liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2' :: (a1 -> a2 -> r) -> (x -> a1) -> (x -> a2) -> (x -> r)
```

By alpha equivalence, it's exactly the same type as `lift`

we made above.

There are similar functions such as `liftM`

, `liftM3`

, `liftM4`

, `liftM5`

, and `liftM6`

. Sorry, I lied. There's no `liftM6`

, 5 is enough! Anyway, they are all about lifting a function with n parameters, making it able to be applied to monadic values. In easy words, it makes functions to work well with some complex values, as we made `&&`

work with complex values, in our case, return values of other functions (`odd`

, `(> 50)`

).

All in all, what I'd like to show in this article is how monad can help us. Monad matters not because it is a monoid in the category of endofunctors, but because it just helps us. You don't need to master category theory or get a Ph.D. in CS before trying Haskell, or even after trying Haskell at all. Please don't be afraid of monad, just enjoy Haskell. Monad will be with you some time, because it's created to help us.

Happy coding!