最近幾年,函數式編程變得越來越流程,其代碼簡潔、副作用小、維護成本低等特點,使得許多其它的語言也開始支持函數式編程,比如`Java` 和 `C#`等。本文主要介紹一下函數式編程中的一個重要概念:`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