Last active
October 15, 2015 13:32
-
-
Save blippy/734f5f49525123b5c42b to your computer and use it in GitHub Desktop.
Exploring Haskell monads using Either
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Exploring Haskell monads using Either | |
Stephan Boyer explained it well why you would want to use monads: | |
http://www.stephanboyer.com/post/9/monads-part-1-a-design-pattern | |
"In each example, we had some functions which we wanted to compose, | |
but their type signatures were incompatible. Our functions took a | |
value of some type and returned a value in the corresponding monadic | |
type." | |
Let us explore this using a function "inc". This function takes a | |
number and adds 1 to it, with a catch: if the input value is greater | |
than 2, it signals an overflow. You could throw an error, for example, | |
but let's use the Either monad. The convention is that you use Left to | |
signal an error, and Right to signal a valid result. Writing this | |
function is easy enough: | |
> inc x = if x > 2 then Left "inc too high" else Right (x + 1) | |
If I type | |
> inc 0 | |
I get | |
> Right 1 | |
So far, so good. The problem is that I cannot compose it with | |
itself. I cannot not type | |
> inc (inc 0) | |
The types are all wrong. What am I going to do? The answer is: use | |
the Either's monadic bind (>>=) operator. Let us look at its type | |
declaration: | |
> (>>=) :: Monad m => m a -> (a -> m b) -> m b | |
Telling us what? It is telling us that (>>=) is a function that takes | |
two arguments: a monad, and a function, and returns another monad. In | |
our case, the monad is the Either monad. | |
The function, which we supply, takes "the thing wrapped by the first | |
argument", and returns a monad. This is exactly what our "inc" | |
function does. It takes an integer, and returns a monad. | |
So now, if we do | |
> Right 0 >>= inc | |
we get the answer we might expect: | |
> Right 1 | |
Note that we cannot do | |
> 0 >>= inc | |
because that doesn't actually make sense. Also note that (>>=) can be | |
used as an infix operator - which is what we have done. | |
Let's experiment some more: | |
> Left "sucka" >>= inc | |
This produces: | |
> Left "sucka" | |
This makes sense. We passed garbage in (via Left), so Haskell returned | |
that same garbage. | |
We can also type | |
> Right 0 >>= inc >>= inc | |
> 2 | |
and also gives us the "compositional form" that we were expecting. | |
What else? | |
> Right 3 >>= inc | |
> Left "inc too high" | |
I hope that is intuitively obvious what happened here. It caused our | |
"overflow condition". | |
Let's try to invoke it another way: | |
> Right 0 >>= inc >>= inc >>= inc >>= inc | |
which again gives | |
> Left "inc too high" | |
Finally, let us use some "syntactic sugar", and replace the (>>=) | |
notation for the more familiar "do" notation: | |
> v4 :: Either [Char] Integer | |
> v4 = do | |
> a <- Right 3 | |
> b <- inc a | |
> return b |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment