Functor
, Applicative
and Monad
three very important concepts in functional programming languages, in particular Monad
, are baffled by how many heroes. In fact, their concept is very simple, but very few an article can describe them clearly, often counterproductive, the more black. Unlike other articles, this article will start from the conclusion, layers of deep, step by step for you to uncover their mystery.
Description : The main code in this article is the Haskell language, which is a purely functional programming language. We don't need to be too concerned about the specifics of the syntax, because it doesn't affect your understanding of this article.
Conclusion
About Functor
, Applicative
and Monad
the concept, in fact, each with a sentence can be summed up:
- One
Functor
is an implemented Functor typeclass
data type;
- One
Applicative
is an implemented Applicative typeclass
data type;
- One
Monad
is Monad typeclass
the type of data that is implemented.
Of course, you might ask what is Typeclass? I think when you see the realization of the word, you should have guessed:
A typeclass is a sort of interface that defines some behavior. If a type is a part of a typeclass, which means that it supports and implements the behavior the Typeclass describes. A lot of people coming from OOP get confused by typeclasses because they think they is like classes in Object oriented LA Nguages. Well, they ' re not. You can think of them kind of as Java interfaces, only better.
Yes, typeclass
it is similar to the Java
interface in, or Objective-C
the protocol in. typeclass
Some functions are defined in, implementing one typeclass
is to implement these functions, and all of the data types that implement this typeclass
will have these common behaviors.
Functor
Applicative
Monad
What is the connection between that and the three, and why do they always trooped? In fact, it Applicative
is an enhanced type Functor
, a data type to be Applicative
the precondition is that it must be, Functor
the same, Monad
is enhanced Applicative
, a data type to become Monad
the precondition is that it must be Applicative
. Note : This connection, when we see Applicative typeclass
Monad typeclass
the definition, will naturally be clear.
Maybe
Before formally starting the introduction Functor
, Applicative
and Monad
the definition, I would like to introduce a very interesting data type, maybe type (can be analogous Swift
Optional
):
The maybe type encapsulates an optional value. A value of type maybe a either contains a value of type a (represented as Just a), or it is empty (represented as nothing) . Using Maybe is a good the deal with errors or exceptional cases without resorting to drastic measures such as error.
Maybe
The type encapsulates an optional value. A Maybe a
value of one type either contains a a
value of one type ( Just a
expressed) or is empty ( Nothing
expressed). We can think Maybe
of it as a box, which may contain a a
type of value, that is, Just a
or an empty box, that is Nothing
. Or, you can interpret it as generics, such as Objective-C
in NSArray<ObjectType>
. However, the most correct understanding should be Maybe
regarded as a context in which the context indicates that a calculation may or may not succeed, that a success is expressed as a result, and that Just a
it is the meaning of the a
Nothing
Maybe
existence of a type:
Let's take a visual look at the Maybe
type:
We can use the box model to understand that it is Nothing
an empty box, but a Just 2
box with 2
this value:
early spoiler : Maybe
type implemented Functor typeclass
, Applicative typeclass
and Monad typeclass
, so it is Functor
, Applicative
and Monad
, details of implementation will be described in the following chapters.
Functor
Before we start the presentation Functor
, let's consider a question like this, if we have a value 2
:
How do we apply a function (+3)
to this value? I think the friends who have been in elementary school should know that this is a simple addition operation:
Minutes to get it done. So the question is, what if the value 2
is in a context? For example Maybe
, at this point, the value 2
becomes Just 2
:
At this point, we cannot directly apply the function (+3)
to Just 2
the. So how do we apply a function to a value in context?
Yes, I think you should have guessed, that Functor
is, to do this, to know how to funeral, please see the next section decomposition.
Functor Typeclass
First, let's look Functor typeclass
at the definition:
Functor typeclass
a function is defined in, fmap
which applies a function (a -> b)
to a value in context f a
and returns another value in the same context f b
, where f
a type placeholder represents any type Functor
.
Note : fmap
The function can be analogous Swift
in the map
method.
Maybe Functor
We know that Maybe
the type is one Functor
and it's implemented Functor typeclass
. We will substitute the type placeholder f
with a specific type to Maybe
be available:
Therefore, for a type, the function that Maybe
it implements fmap
is to apply a function (a -> b)
to a value in context Maybe
Maybe a
and return another Maybe
value Maybe b
in context. Next, let's take Maybe
a look at Functor typeclass
the specifics of the type implementation:
There are Maybe
two situations where the context is handled separately: if there is a value in the box, that is, it is taken out of the Just x
x
box, then the function is func
applied, and the result is put into x
a new box of the same type, and if the box is empty, Then return directly to a new empty box.
See here, I think you should already know how to apply a function to a value in context. As mentioned earlier, the function is (+3)
applied to Just 2
:
Also, it is worth mentioning that when we apply the function (+3)
to an empty box, that is Nothing
, we will get a new empty box:
Applicative
Now, we already know how to apply the function (+3)
to Just 2
the. Then again, if the function (+3)
is in context, for example, at Maybe
this point, the function (+3)
becomes Just (+3)
:
So how do we apply a function in context to a value in context?
This is Applicative
the thing to do, please see the following section for details.
Applicative Typeclass
Again, let's take a look Applicative typeclass
at the definition:
We note that, unlike Functor typeclass
the definition, there is Applicative typeclass
a more class constraint in the definition, meaning that the Functor f
data type is to be implemented as a precondition that f
Applicative typeclass
it must be implemented, that Functor typeclass
is, it must be a Functor
.
Applicative typeclass
two functions are defined in:
pure
: Puts a value a
into context;
(<*>)
: Applies a function in context f (a -> b)
to a value in context f a
and returns another value in context f b
.
Note : <*>
the pronunciation of the function I do not know, if any students know the words also please tell, thank you.
Maybe applicative
Similarly, we will substitute the type placeholder f
with a specific type to Maybe
get:
Therefore, for Maybe
a type, the function that it implements is to pure
put a value a
into Maybe
context. The function, however (<*>)
, is to apply a Maybe
function in context Maybe (a -> b)
to a value in context Maybe
Maybe a
and return another Maybe
value Maybe b
in context. Next, let's take Maybe
a look at Applicative typeclass
the specifics of the type implementation:
pure
The implementation of the function is very simple and can be directly equal Just
. And for (<*>)
the implementation of the function, we also need to Maybe
deal with the context of the two cases: when the box is empty, directly return a new empty box, when the box loaded function is not empty, that is Just func
, func
take out, use the fmap
function to func
directly Applied to the value in the context, this is exactly what we said earlier about the Functor
function.
OK, let's take a look at Just (+3)
the specific process that will be applied Just 2
:
Similarly, when we apply an empty box, that is, Nothing
Just 2
we will get a new empty box:
Monad
So far, we've learned that Functor
the effect is to apply a function to a value in a context:
Applicative
the effect is to apply a function in a context to a value in a context:
So Monad
what's it going to be? In fact, Monad
the function Functor
is similar to that of applying a function to a value in a context. The difference is that a function that receives a normal value and returns a normal value is applied to Functor
Monad
a function that receives a normal value but returns a value in context:
Monad Typeclass
Again, let's take a look Monad typeclass
at the definition:
Wow, what a ghost, completely do not understand ah, too complex. Brother Tai Mo Urgent, and listen to me in detail. In the Monad typeclass
four functions defined in, are,, return
and, and the (>>=)
(>>)
fail
following two functions (>>)
and fail
give the default implementation, and in the vast majority of cases, we do not need to rewrite them. Therefore, after removing these two functions, Monad typeclass
the definition can be simplified to:
What do you think? It looks a lot better now. Applicative typeclass
As with the definition, Monad typeclass
there is also a class constraint in the definition Applicative m
, meaning that a data type must be a m
Monad
precondition for it to be Applicative
. In addition, the function of functions and functions of the function return
Applicative
is the pure
same, except for a name, their role is to put a value a
into the context. (>>=)
the function is to apply a function (which receives a normal value a
but returns a value in context m b
) (a -> m b)
to a value in one context m a
and returns another value in the same context m b
.
Note : The pronunciation of the >>=
function is bind
, ReactiveCocoa
students should pay attention to learning. In addition, the >>=
function can be analogous to Swift
the flatMap
method.
Maybe Monad
Similarly, we will substitute the type placeholder m
with a specific type to Maybe
get:
I believe you can easily understand the above two functions with the box model, so we don't repeat them. Next, let's take Maybe
a look at Monad typeclass
the specifics of the type implementation:
As previously mentioned, return
the implementation of a function pure
is like a function, which is directly equal to the function Just
, and the function is to put a value into the x
Maybe
box Just x
. Similarly, for the (>>=)
implementation of the function, we need to deal with the Maybe
context of the two cases, when the box is empty, directly return a new empty box, when the box is not empty, that is Just x
, x
take out, directly func
apply the function to x
, and we func x
The result you know is a value in context.
Let's take a look at a concrete example. We first define a half
function that takes a number as an x
argument, and if x
it is even, divides it and puts the result in the box, and if it is x
2
Maybe
x
Not even, returns an empty box:
Next, we use the function (>>=)
half
to apply the function to the Just 20
assumption that the result is obtained, y
and then continue to use the function to apply the (>>=)
half
function to the result of the previous step, and y
so on, to see what the result will be:
See the above operation process, do not know if you see what is the clue? The output from the previous step is the next input, and the process can go on indefinitely if you wish. I think you might have thought of it, yes, it's a chain-like operation. All operations are linked like a production line, each step of the operation is to process the input, and then produce the output, the entire operation process can be seen as the original raw material Just 20
processing and ultimately produce the finished product Nothing
process:
Note : Chained operations are only Monad
one of the major benefits for us; Another major benefit that this article does not cover is that we Monad
can automate the context for us, and we just need to care about the real value.
Reactivecocoa
Now that we know Monad
what it is, it is a Monad typeclass
type of data that has been implemented. So what specific application does it have? You can't let us all do theoretical research. In this case, we have to sacrifice the Objective-C
artifact, ReactiveCocoa
it is based on Monad
the concept of building up. The following is RACStream
the inheritance structure diagram:
RACStream
is the ReactiveCocoa
core of the class, it is a Monad
:
As we can see, we RACStream
've defined two methods that look very familiar:
+ (instancetype)return:(id)value;
;
- (instancetype)bind:(RACStreamBindBlock (^)(void))block;
。
Where the return:
function of a method is to put a value value
into RACStream
context, and the bind:
function of a method is RACStreamBindBlock
to apply a type block
to a RACStream
value in context ( receiver
) and return another in RACStream
context Value. Note , the RACStreamBindBlock
type block
is a "function" that receives a normal value value
but returns a RACStream
value in context:
Next, to deepen our understanding, let Monad typeclass
's compare the definitions:
Similarly, we will substitute the type placeholder for m
the RACStream
following:
where the return :: a -> RACStream a
corresponding + (instancetype)return:(id)value;
, and (>>=) :: RACStream a -> (a -> RACStream b) -> RACStream b
then corresponding - (instancetype)bind:(RACStreamBindBlock (^)(void))block;
. Note : As we have mentioned before, the >>=
pronunciation of the function is bind
. As a result, you ReactiveCocoa
will have the following gameplay:
Monad
Like the ReactiveCocoa
Tai chi, Tai Chi Sheng Two, two Miriam born four elephant, four elephant gossip. At this point, we already know the ReactiveCocoa
core of the principle, and more about ReactiveCocoa
the content we will be in the subsequent source code analysis to introduce, please look forward to.
Summarize
Functor
, Applicative
and Monad
what it is:
- One
Functor
is an implemented Functor typeclass
data type;
- One
Applicative
is an implemented Applicative typeclass
data type;
- One
Monad
is Monad typeclass
the type of data that is implemented.
Functor
, Applicative
and Monad
the links between the three:
Applicative
is an enhanced type Functor
, a data type must be a Applicative
precondition for it to be Functor
;
Monad
is an enhanced type Applicative
, a data type to be a Monad
precondition is that it must be Applicative
.
Functor
, Applicative
and Monad
the difference between the three:
Functor
: Use the fmap
value of applying a function to a context;
Applicative
: Use a <*>
function in a context to apply a value in a context;
Monad
: Use >>=
an application that receives a normal value but returns a value in context to a value in a context.
In addition, we have introduced a very interesting data type Maybe
, it implements Functor typeclass
, Applicative typeclass
and Monad typeclass
, so it is Functor
, Applicative
and Monad
.
Above is the whole content of this article, hope can be helpful to you, good luck!
Reference links
Http://learnyouahaskell.com/chapters
Https://downloads.haskell.org/~ghc/latest/docs/html/libraries
Http://adit.io/posts/2013-04-17-functors,applicatives,and_monads_in_pictures.html
Original link: http://blog.leichunfeng.com/blog/2015/11/08/functor-applicative-and-monad/
Functor, Applicative and Monad