iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 24
0
Software Development

Functional Programming in JS系列 第 24

Functor 4: 圖解 Box Data Type 之方法 map、flatMap、chain

Functor 對初學者來說實在有點難懂,所以不知不覺已來到第四篇,希望看完這一系列可以真的懂他在幹嘛。 基本上除了系列 1 之外,其他都是在探究 Box 這種 data type
https://ithelp.ithome.com.tw/upload/images/20200925/20106426cgJAqD2xtT.jpg
(↑ 不知道已出現幾次的 Box data type 圖)

Map

神奇的運算 map 能接受 Functor 當作輸入參數,回傳另一個 Box。

雖然前面其實已經說過這是什麼,但需要再強調複習一次
https://ithelp.ithome.com.tw/upload/images/20200925/20106426us8pdxIQqy.jpg

const Box = f => ({
    map: g => Box( x => g(f(x)) ),
}

FlatMap

un-nest 扁平化,接受 Functor 當作參數,回傳把最外層 Context 拿掉後裡面的東西

像上圖,很常時候我們為了避免 Side Effect 例如 Math.random()console.log ,會先把他們丟到一個 Box 裡,但這樣做完運算會回傳 nesting 的 Box (也就是 Box 會包在另一個 Box,可以看下圖比較好懂),這樣導致後面運算變複雜,所以才會有這個方法,讓他 un-nest 扁平化,變成只要一層 Box 就好

同義詞還有 Joinbind(Haskell) 的說法但我個人比較喜歡 flatMap 較符合方法實際在做的事。

https://ithelp.ithome.com.tw/upload/images/20200925/20106426lbbrfW5Dv3.jpg

const Box = f => ({
    flatMap: x =>  f(x)
}

若我們把前一篇提過的 runEffect 也放進來。

const Box = f => ({
    flatMap: x =>  f(x),
    runEffect: x=> f(x)
}

恩?你可以會有疑惑說 runEffectflatMap 不是一模一樣嗎?
沒錯,當然你可以只用一個就好,但 runEffect 顧名思義我們都拿來執行 Effect 檢視內容。但若我們只是想要扁平化,除掉 nest 而已,並沒有想導致 Side Effect 但卻用 runEffect 這個名稱似乎有點怪,所以還是建議分開寫成兩個方法

Chain

map + flatMap

程式寫到最後會發現不斷再 .map().flatMap() 那不如直接寫一個快速方法是包含這兩個方法的
https://ithelp.ithome.com.tw/upload/images/20200925/20106426VmWvB09n00.jpg

const Box = f => ({
    map: g => Effect( x => g(f(x)) ),
    flatMap: x =>  f(x),
    chain: g =>  Effect(f).map(g).flatMap()
}

下一篇會實際用程式解說以上方法


如有錯誤或需要改進的地方,拜託跟我說。
我會以最快速度修改,感謝您

上一篇
Functor 3: 程式碼解說篇
下一篇
Functor 5: 用 Effect functor 解決真實世界的 Side Effect
系列文
Functional Programming in JS30

尚未有邦友留言

立即登入留言