圖解

2018-02-24 16:09 更新

1.

軟件最基本的數(shù)據(jù),就是各種值(value)。

2.

處理值的一系列操作,可以封裝成函數(shù)。輸入一個(gè)值,會(huì)得到另一個(gè)值。上圖的"(+3)"就是一個(gè)函數(shù),對(duì)輸入的值加上3,再輸出。

3.

函數(shù)很像漏斗,上面進(jìn)入一個(gè)值,下面出來(lái)一個(gè)值。

4.

函數(shù)可以連接起來(lái)使用,一個(gè)函數(shù)接著另一個(gè)函數(shù)。

5.

函數(shù)還可以依次處理數(shù)據(jù)集合的每個(gè)成員。

6.

說(shuō)完了函數(shù),再來(lái)看第二個(gè)概念:數(shù)據(jù)類型(type)。

數(shù)據(jù)類型就是對(duì)值的一種封裝,不僅包括值本身,還包括相關(guān)的屬性和方法。上圖就是2的封裝,從此2就不是一個(gè)單純的值,而是一種數(shù)據(jù)類型的實(shí)例,只能在數(shù)據(jù)類型的場(chǎng)景(context)中使用。

7.

2變成數(shù)據(jù)類型以后,原來(lái)的函數(shù)就不能用了。因?yàn)?(+3)"這個(gè)函數(shù)是處理值的(簡(jiǎn)稱"值函數(shù)"),而不是處理數(shù)據(jù)類型的。

8.

我們需要重新定義一種運(yùn)算。它接受"值函數(shù)"和數(shù)據(jù)類型的實(shí)例作為輸入?yún)?shù),使用"值函數(shù)"處理后,再輸出數(shù)據(jù)類型的另一個(gè)實(shí)例。上圖的fmap就代表了這種運(yùn)算。

9.

fmap的內(nèi)部,實(shí)際上是這樣:打開(kāi)封裝的數(shù)據(jù)類型,取出值,用值函數(shù)處理以后,再封裝回?cái)?shù)據(jù)類型。

10.

一個(gè)有趣的問(wèn)題來(lái)了。如果我們把函數(shù)也封裝成數(shù)據(jù)類型,會(huì)怎樣?

上圖就是把函數(shù)"(+3)"封裝成一種數(shù)據(jù)類型。

11.

這時(shí),就需要再定義一種新的運(yùn)算。它不是值與值的運(yùn)算,也不是值與數(shù)據(jù)類型的運(yùn)算,而是數(shù)據(jù)類型與數(shù)據(jù)類型的運(yùn)算。

上圖中,兩個(gè)數(shù)據(jù)類型進(jìn)行運(yùn)算。首先,取出它們各自的值,一個(gè)是函數(shù),一個(gè)是數(shù)值;然后,使用函數(shù)處理數(shù)值;最后,將函數(shù)的返回結(jié)果再封裝進(jìn)數(shù)據(jù)類型。

12.

函數(shù)可以返回值,當(dāng)然也可以返回?cái)?shù)據(jù)類型。

13.

我們需要的是這樣一種函數(shù):它的輸入和輸出都是數(shù)據(jù)類型。

14.

這樣做的好處是什么?

因?yàn)閿?shù)據(jù)類型是帶有運(yùn)算方法的,如果每一步返回的都是數(shù)據(jù)類型的實(shí)例,我們就可以把它們連接起來(lái)。

15.

來(lái)看一個(gè)實(shí)例,系統(tǒng)的I/O提供了用戶的輸入。

16.

getLine函數(shù)可以將用戶的輸入處理成一個(gè)字符串類型(STR)的實(shí)例。

17.

readfile函數(shù)接受STR實(shí)例當(dāng)作文件名,返回一個(gè)文件類型的實(shí)例。

18.

putStrLn函數(shù)將文件內(nèi)容輸出。

19.

所有這些運(yùn)算連起來(lái),就叫做Monad。

簡(jiǎn)單說(shuō),Monad就是一種設(shè)計(jì)模式,表示將一個(gè)運(yùn)算過(guò)程,通過(guò)函數(shù)拆解成互相連接的多個(gè)步驟。你只要提供下一步運(yùn)算所需的函數(shù),整個(gè)運(yùn)算就會(huì)自動(dòng)進(jìn)行下去。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)