談談我對Monad的理解

weixin_34249678發表於2016-05-25

一、迷失於Monad的汪洋大海

第一次看見這個概念是兩年前,這個詞有著非常不通俗的翻譯:“單子”。那時候受王垠影響在看Scheme和Haskell,對於Scheme的continuation和Haskell的Monad百思不得其解。直覺告訴我,這倆貨之間有著千絲萬縷的聯絡。當時對於型別可計算的概念也是毫無概念,作為剛從Java Web轉到程式語言研究的我真是菜的不行,如飢似渴的在網上找資料各種讀,越讀越迷惑,後來不得不放下。

二、和Monad的幾個照面

而後自己寫了幾個很菜的編譯器,和效能啊新特性啊什麼的毫不沾邊。

看別人部落格的文章照貓畫虎也寫過Monadic的語法分析器,也用過C#大法的Linq,然而並沒有使我明白Monad是個啥。

Linq中的

from a in A
from b in B
from c in C
select f(a,b,c)

其實可以轉化為這種結構:

A.SelectMany(a=>
    B.SelectMany(b=>
        C.Select(c=> f(a,b,c)
        )
    )
);

再後來在深入淺出node.js裡見識了js的巢狀callback,因此看到了promise。
巢狀callback的程式碼:

A.fuck1(function(a){
    B.fuck2(function(b){
        C.fuck3(function(c){
            f(a,b,c);
        }
    }
});

promise把巢狀callback改寫成這種風格(大概,虛擬碼):

Promise.then(A.fuck1)
       .then(B.fuck2)
       .then(C.fuck3)
       .then(function(a,b,c){
             f(a,b,c);
       })
       .done();

當時讀來毫無感覺,現在細想毛骨悚然。

熟悉Scheme的孩子應該一眼就能發現這裡面有CPS變換。

所謂CPS變換就是把所有g(f(x))都給改寫成f(x, r=>g(r))的過程。然而這有和Monad有什麼關係?Monad到底是個啥?

CPS變換和Monad是一家親。CPS變換是說變換過程,而Monad是具備某種能力的“物件”。所謂具備某種能力其實就是Monad具備這種把巢狀式的金字塔結構打平成鏈式結構的能力。Promise差不多算是和Linq有異曲同工之妙。兩者都是Monad的應用。Monad的定義涉及了一些型別計算,其實是很簡單的東西,只是寫成學術符號立刻讓人看不懂了。

最近讀了一篇文章聯想起之前的Linq和promise,彷彿是有點恍然大悟的感覺。

在Swift裡,“一個實現了 flatMap方法的型別其實就是 monad”。

public func flatMap<U>(f: (Wrapped) -> U?) -> U? { 
    switch self { 
        case .Some(let y): return try f(y) 
        case .None: return .None 
    }
}

flatMap接受一個函式f做引數,返回一個Optinal U型別。f接受Optional型別包裹的型別,返回Optinal U型別。
下面是Optional的定義:

enum Optional<T> { 
    case None 
    case Some(T)
}

這只是一個很小的關於Optianal<T>的簡單例子,其實實現了flatMap的類都可以稱作Monad。

當然Monad可不僅僅是這樣,當年在Haskell裡面反正是看的雲裡霧裡。熟悉型別推導的孩子可以推導一下型別,看看為毛promise可以寫成那樣。哦,我忘了,js是弱型別的!

其實這篇文章我倒沒打算把Monad講明白,因為畢竟我是跌跌撞撞走過了很多彎路才明白了型別計算,continuation才最終走到了Monad面前,不敢說自己有什麼理解,只是通俗的明白了這貨原來真的有用,而且用的還不少,只是學術性太強導致曾經看過的資料總有些說不清道不明,感覺有道鴻溝橫在眼前。

之所以寫這篇是因為我知道這個概念太久,如鯁在喉。

貼上兩篇有啟發的文章:

http://www.infoq.com/cn/articles/swift-brain-gym-monad?utm_campaign=rightbar_v2&utm_source=infoq&utm_medium=articles_link&utm_content=link_text

http://www.cppblog.com/vczh/archive/2013/07/27/202154.html

最後感慨一下,vczh大神的高度果然不是我這等渣渣可以企及的。當年太菜沒看懂幾篇vczh的部落格,淚流滿面。

相關文章