Monad comprehensive tutorial
what is monad
functor
functor can be interpreted as A container that is mappable between categories.endofunctor is a functor that mappable inside single category.
First of all, by saying container, it would definitely hold something inside, whether it is a single value or a set of value or nothing at all.
Another important property is mappable, which means the data inside the container can be transformed into another by a map function.
This is how we do the work:
- grab the data from inside the container
- use a mapping logic to transform all the data
- put the transformed them into a new container
1 | |
The usage can be as follow:
1 | |
So we call Wrapper is a functor, we can place data into it and use map function to do data transformation.
function
function is basically a map between 2 objects
Mathematically speaking
$$
f(x) = y
$$
where $f, x, y$ is called symbol
$f$ is the mapping logic between input and output.
$x$ is the input and $y$ is the output, we do not care about the type of these 2 symbols, they can be concrete value and can also be mapping logic(function)
This formation can be written into another one
$$
f: x \rightarrow y
$$
Because $x, y$ can be function themselves, then it is called high-order function
curry
For function with multiple input, can use a technique named partial apply to reduct it into single input function, this is called curry, for instance:
Say we have an expression (+ a b) where both a and b are input, we can transform it into 2 partial function, and can be executed one by one in order to align with the original expression.
In clojure we can use partial function to currify the multi-input function
1 | |
curry is essentially the transformation of below:
$$
(a, b) \rightarrow c \equiv a \rightarrow (b \rightarrow c)
$$
This transform multi-input function into a single input function, which returns another function that is single input as well.
By mathematical convention in lambda calculus, the right arrow would associate first, so the formation above would become:
$$
a \rightarrow (b \rightarrow c) \equiv a \rightarrow b \rightarrow c
$$
If we rewrite the formation above in clojure, in order to guarantee associativity:
1 | |
Let’s see a concrete example:
1 | |
In Clojure or Javascript, p and q are different functions, but they mathematically are exactly the same.
example
We will provide 2 examples to illustrate how and where monad comes from:
future
Given 2 functions as below that could do single work:
1 | |
These 2 functions are in this form:
$$
a \rightarrow \text{Future}\space b\quad \text{or} \quad a \rightarrow \text{C}\space b
$$
It is the container Future that hold the data.
1 | |
Now the compose function is of type:
1 | |
List
Given 2 functions like below:
1 | |
These 2 functions are in this form, $a \rightarrow [b]$.
If we rewrite the list symbol as another type, we have:
$$
a \rightarrow \text{List}\space b\quad \text{or}\quad a \rightarrow \text{C}\space b
$$
where List is the container and b is the value inside.
1 | |
monad
We observe that not only asynchronous future but also list follow the same pattern:
$$
a \rightarrow \text{C}\space b
$$
Where C is the mappable container, this is the functor that we mentioned above.
We can also try to use function composition, such as:
$$
(a \rightarrow C\ b) \rightarrow (x \rightarrow C\ a) \rightarrow (x \rightarrow C\ b)
$$
When we replace C with future we get asynchronous invocation function; when replace with list, we get list transformation function. If we use identity as C, then it is the regular function.
$$
\begin{aligned}
\because&\ \text{Identity}\ a \equiv a\
\therefore&\ (a \rightarrow \text{Identity}\ b) \equiv (a \rightarrow b)
\end{aligned}
$$
Then we want to define identity unit, because of associativity, the identity is as below:
1 | |
We can see compose function is of type:
1 | |
We can determine the type of identity: (a -> C a)
For future the identity is:
1 | |
For list the identity is:
1 | |
We observe that both future and list has identity unit. Is this always the case?
The answer is true if we go with monad, as the definition of it is:
1 | |
monoid would of course has identity according to its definition, and it maps objects in one category.
Now let’s define function bind:
1 | |