Why do we need monads?
- We want to program only using functions. (“functional programming (FP)” after all).
-
Then, we have a first big problem. This is a program:
f(x) = 2 * xg(x,y) = x / yHow can we say what is to be executed first? How can we form an ordered sequence of functions (i.e. a program) using no more than functions?
Solution: compose functions. If you want first
gand thenf, just writef(g(x,y)). This way, “the program” is a function as well:main = f(g(x,y)). OK, but … -
More problems: some functions might fail (i.e.
g(2,0), divide by 0). We have no “exceptions” in FP (an exception is not a function). How do we solve it?Solution: Let’s allow functions to return two kind of things: instead of having
g : Real,Real -> Real(function from two reals into a real), let’s allowg : Real,Real -> Real | Nothing(function from two reals into (real or nothing)). -
But functions should (to be simpler) return only one thing.
Solution: let’s create a new type of data to be returned, a “boxing type” that encloses maybe a real or be simply nothing. Hence, we can have
g : Real,Real -> Maybe Real. OK, but … -
What happens now to
f(g(x,y))?fis not ready to consume aMaybe Real. And, we don’t want to change every function we could connect withgto consume aMaybe Real.Solution: let’s have a special function to “connect”https://stackoverflow.com/”compose”https://stackoverflow.com/”link” functions. That way, we can, behind the scenes, adapt the output of one function to feed the following one.
In our case:
g >>= f(connect/composegtof). We want>>=to getg‘s output, inspect it and, in case it isNothingjust don’t callfand returnNothing; or on the contrary, extract the boxedRealand feedfwith it. (This algorithm is just the implementation of>>=for theMaybetype). Also note that>>=must be written only once per “boxing type” (different box, different adapting algorithm). -
Many other problems arise which can be solved using this same pattern: 1. Use a “box” to codify/store different meanings/values, and have functions like
gthat return those “boxed values”. 2. Have a composer/linkerg >>= fto help connectingg‘s output tof‘s input, so we don’t have to change anyfat all. -
Remarkable problems that can be solved using this technique are:
-
having a global state that every function in the sequence of functions (“the program”) can share: solution
StateMonad. -
We don’t like “impure functions”: functions that yield different output for same input. Therefore, let’s mark those functions, making them to return a tagged/boxed value:
IOmonad.
-
Total happiness!