Monads for Great Fun
Tags: haskell, monads, programming
Published: 2023-03-04 03:11:52

One of my favorite books on Haskell is Learn You a Haskell by Miran Lipovača. Often monads are interpreted in a mathematical or purely functional context, and this is the approach in Learn You a Haskell. However, their reach goes far beyond that. In this tutorial, I won't entirely explain what monads are; I assume you already have a decent knowledge of this. If not, read the monad section of the book or read another tutorial like on the [Haskell](https://www.haskell.org/tutorial/monads.html) site. 

Instead, I will show you what monadic computation is capable of in terms of various interesting applications. To briefly review, a monad is a computational context with an operator bind (>>=) which takes in a monadic value then applies a function to the unwrapped value and returns another monad. It's like a wrapper that wraps another value with context. Looking at the type signature you can see what I mean.

```haskell
(>>=) :: m a -> (a -> m b) -> m b
```
Another operator (>>) does the same thing but without any input. This operator merely chains together two monads without any function applied.
```haskell
(>>) :: m a -> m b -> m b
```

The do syntax just does (>>) repeatedly without needing to write the operator explicitly. For example we could write the following code.
```haskell
doSomething = Just 2 >> Just 3 >> Nothing
```
In this do form.
```haskell
doSomething = do
    Just 2
    Just 3
    Nothing
```

We can use the (<-) operator to unwrap the monadic value and return a normal unwrapped value. For example, getting a line of text from an IO monad and printing the value.
```haskell
main = do
    ln <- getLine
    putStrLn ln
```

But there are some there example where Monads might be very useful. I'll go over a few of these.

## HTTP 

One example would be for HTTP authentication passing. I'm not familiar if existing frameworks like Yesod implement this or not. However, we could do something like this to store an authentication context instead of having to pass it each time as a header.

```haskell
getFromWeb :: HTTP ()
getFromWeb = do
    authentication "Bearer: TOKEN"
    res1 <- get "http://someurl.com/api/get"
    post "http://someurl.com/api/post" "{JSON data}"
```

The authentication function would return a HTTP monad with the authentication context of a bearer token.


## Graphics

Often times drawing is implemented as a complex state machine with many parameters to keep track of. For example in OpenGL you have to set the viewport then the vertex arrays and so on. In Processing and Javascript with the canvas you have to do something similar like this.

```javascript
const ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.moveTo(50, 140);
ctx.lineTo(150, 60);
ctx.lineTo(250, 140);
ctx.closePath();
ctx.stroke();
```
This is the perfect example to "monadize." We could write something similar using a path monad like this.

```haskell
stroke :: Context2D -> Path -> DrawIO
createShape :: Path
createShape = do
    moveTo 50 140
    lineTo 150 60
    lineTo 250 140
    
main :: DrawIO
main = do
    stroke $ (createContext "2d") createShape
```

No more needing to keep track of where the path begins and ends and we no longer need to keep track of the drawing context.

## Sound

I was thinking of applying monads to signal processing for audio. Let's say we have a signal monad which carries context about the signal. Imagine we took in an input signal and passed it through a low-pass-filter at 440hz and then a delay line of 0.5ms, it might look something like this with binds.

```haskell
filterAndDelay :: Signal -> Signal
filterAndDelay input = 
    input >>= lpf 440 >>= delay 0.5
```