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 |
|