Monad is a structure with type constructor M and two functions unit (η) and multiplication (μ).
and
To lift value from a to Ma we need unit function and to flatten from M(Ma) to Ma we need multiplication.
Why do we need monad in functional programming? Why do we need functional programming anyways?
Functional programming is a paradigm which uses pure functions to build an application. The power of pure functions are, we can compose them and we can build complex things out of the small and simple functions.
If we have these functions
and
We can get
We can use below general purpose compose function to compose any two pure functions.
If we need to compose three functions then we can do like
Now, we can't build application using only pure functions. It is next to impossible. We need side effects anyways to make the application practical in use. To achieve the goal, we need to keep pure functions in center/core part of application and need to move side effects outside of core layer as much as possible.
How can we achieve this?
Side effects may occur at any part of application. (e. g. console log, taking input from user, writing/reading files, sending/receiving data to/from network, handling future value (asynchronous scenario), handling errors etc.)
As pure function returns same exact value for particular input values always, pure function can't stay pure if it tries to handle any of the above scenario.
Suppose, we have a function below, it throws error if value is zero.
This is not a pure function as it has side effect. How can we make it pure and can delay or wrap the side effect and move it to outer layer of application?
We have used Either here. Either is a monad. We wrapped success and failure both case in same monad. So, our function will always return the Either in both of the scenario. It became pure now.
If we do not use Either we need to handle error right away or need to throw error again which does not make any function pure and increases code complexity too.
If we use Either we can handle the error later.
This way we are moving side effects to outer layer as much as possible and trying to make function pure in core code.
Did you notice map function in code? Functor has map function, and monad is a functor too, so lets take a brief introduction of functor.
Functor lifts values and functions between those values.
If we have function
then functor F lifts a to Fa, b to Fb and f to Ff. This way, we have another function like,
To get the new function Ff we can reuse original function f, the Ff can be called map too.
Functor has limitation. It just lifts values and functions, it can't unlift or flatten it. That is where monad comes into picture. Lets continue with monad.
Function which returns monadic value looks like this.
So, if we want to compose functions which returns monadic value we can do this.
But, wait... Before, it was straightforward, we have b from first function and need to pass the same b to second one. How can we convert Mb to b, and make the functions composable.
We need to define an extra function to make this whole expression looks like compose.
The extra function is
Notice that this is multiplication or μ (can be called flatten or join too).
So, including the above function in normal compose, we can make functions returning monadic value composable.
There is another function we need to pay some attentions to it is..
This is not the same as
But, as monad is a functor too. We can find the map for above scenario as..
So, new compose will become like..
To make composition work we introduce two functions map and flatten here. As composition always evaluates in revers order, we can call combined function of these both as flatMap. If you ever worked with monad you can recall flatMap.
Now, we can create pure functions hiding / delaying side effects and we can compose that functions as well.
We have type constructor M, so it is good to define a function which can accept value, lifts it (using type constructor) and returns monadic value.
This is called unit or η (can be called return too).
If we describe monad very simply than..
Monad is a container / context / structure for value with type constructor M, and functions unit and multiplication.
This is very basic and summarized article of monad.
We will see complex and in-depth understanding of monad using category theory in next article.
Comments
Post a Comment