Jul 27, 2009

Ubiquitous Monad

It seems I had an 'aha!' time with monad today, finally. It seems monad is everywhere.

In a functional world with currying, we can think all functions are in the type x -> y. We can divide those functions into two category:

1. a -> a, these are functions who have same input and output type 2. a -> b, there are the functions who have different input and output type

Functions in category one can work with functions have the same type as them easily, suppose you have f::Int->Int and g::Int->Int, you can combine them as you wish, like f.f.f.g.g.g.f.g.g.f. This is why people like functional programming.

But this is not true for functions in 2rd category. Suppose you have f::Int->Float and g::Int->Float, how would you combine them? You can do neither f.g nor g.f, the types just don't match. As you can feel, there's much more functions in 2rd category than those in 1st category in real world. So monad comes to rescue.

Monad helps functions in 2rd category behave like those ones in 1st category - it can 'lift' a 2rd category function to 1st category, with one of its core functions named bind:

bind :: (a -> b) -> (b -> b)

In haskell b is a Monad. If you have read a tutorial take Maybe monad as example, you may have an intuition that monad is a 'wrapper' which wrap something. That's not exactly. The key here is to define a way to convert a value of type a to a value to type b, and vice vesa. Wrap a value is an easy and intuitive way to do the conversion, but not the only way (e.g. List Monad is a good example). So you can think everything as Monad, because type a -> b function is everywhere. Yes Float is monad, because there is a function in type Int -> Float and you can define a bind in type (Int -> Float) -> (Float -> Float).