Monad详解
最近几年,函数式编程变得越来越流程,其代码简洁、副作用小、维护成本低等特点,使得许多其它的语言也开始支持函数式编程,比如Java
和 C#
等。本文主要介绍一下函数式编程中的一个重要概念:Monad
。
从定义上看,Monad
就是两个接口:一个是return
,另一个是一个bind
;只要实现这两个操作的类型,都是monad
。但是在理解Monad
之前,先要搞清楚两个概念:Functors
和 Applicatives
:
1. Functors
-
定义:把一个函数作用在数值类型(对值类型的封装,包含相关属性和方法)上,用
fmap
或者<$>
表示这种运算。 -
常规运算:把一个函数作用在一个普通数值上
- Functors运算: 如果把普通数值用上下文包括,生成一个数值类型,那么函数将无法处理该数值类型
函数无法处理数值类型,于是就出现了Functors
,它可以处理数值类型,例如:
> fmap (+3) (Just 2)
Just 5
或
> (+3) <$> (Just 2)
Just 5
具体操作步骤如下图解:
如果数值类型为Nothing,那么Functors作用后的结果也是Nothing:
2. Applicatives
-
定义: 把一个封装后的函数作用于数值类型(对值类型的封装,包含相关属性和方法),用
liftA
或<*>
定义这种运算。 -
运算法则:可以把
Applicatives
看成是Functors
中的函数也被封装了一层,然后再应用于数值类型
> Just (+3) <*> Just 2
Just 5
或
> liftA (Just (+3)) (Just 2)
Just 15
如果数值类型为Nothing,那么Functors作用后的结果也是Nothing:
3. Monad
-
定义: 把一个返回数值类型的函数作用于数值类型,用
liftM
或>>=
来定义这种运算。 -
运算法则:可以把
Monad
看成是Applicatives
中的函数返回值也是数值类型
定义half
是判断是否是偶数的函数, 作用于数值类型20,过程如下:
> Just 20 >>= half >>= half >>= half
Nothing
如果数值类型为Nothing,那么Functors作用后的结果也是Nothing:
由于Nothing
作用于Functors
、Applicatives
和Monad
时,都返回Nothing
,所以它们都是Maybe
类型。Maybe
类型的定义如下:
data Maybe a = Nothing | Just a
参考资料
http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
http://www.ruanyifeng.com/blog/2015/07/monad.html?utm_source=tuicool