composition(組合) 是函數(shù)式編程的基石缺前。但是實(shí)現(xiàn)組合并不是一件簡單直接的事情扼脐。除了前一節(jié)我們介紹的概念祈争,還需要基礎(chǔ)的數(shù)學(xué)知識买置。
從數(shù)學(xué)說起
先看個公式:
若 y = f(x)辟狈,z=g(y) 瓶蚂, 則 z= g(f(x))
這個我們都是認(rèn)可的糖埋,因?yàn)閮蓚€ y
是指同一個值。那我們變一下:
若 y' = f(x) 窃这, z=g(y'') 瞳别, 則 z ??
這里 z
應(yīng)該怎么寫? 我們犯難了,因?yàn)?y'
和 y''
不一定是同一個值杭攻,如果再有一個函數(shù)m
祟敛, 使得y'' = m(y')
則 z = g(f(m(y')))
。這個函數(shù) m
即是 y'
到 y''
的映射兆解, 寫出來就是 y => m(y)
馆铁。 這樣的函數(shù)在編程語言中是很常見的,比如 Array.map
, Int.toString
等都是這樣的函數(shù)锅睛。
Compose (組合)
看了上面的問題埠巨,我們這里討論下組合即滿足集合的條件。組合其實(shí)就是拼接衣撬。
一般來說乖订,要拼接,要滿足以下規(guī)則:
- 順序性具练,鏈接的各個部件之間要有順序乍构。
- 可拼接性,前一個尾部連接點(diǎn)和后面的鏈接點(diǎn)個數(shù)量扛点,類型要匹配哥遮。
回到我們的編程世間里,上面說的要鏈接的部件其實(shí)就是變量和函數(shù)陵究。(也就解釋了在函數(shù)式編程中函數(shù)為什么是一等公民眠饮,因?yàn)樗兞恳粯涌梢员毁x值和傳遞。)所以順序性就是函數(shù)和變量的順序铜邮。這個可以有業(yè)務(wù)和邏輯可以來保證仪召。那可拼接性就是前一個變量 / 函數(shù)入?yún)⒌膫€數(shù)和類型要近跟著的一致寨蹋,這不是一個簡單的事情。
首先扔茅,對于函數(shù)來說已旧,入?yún)⑹遣淮_定,從 0 ... n
都是有可能的, 且類型可以同一個轉(zhuǎn)換函數(shù) m
解召娜,數(shù)量怎么解決运褪?更嚴(yán)重的問題是函數(shù)的返回值永遠(yuǎn)只有一個。如何讓一個函數(shù)返回值玖瘸,滿足一個函數(shù)入?yún)⒔斩铮柯斆鞯哪憧赡軙R上說道,那用一個 object
就可以了雅倒。
對就是這樣解決的璃诀,我們將函數(shù)入?yún)⑷糠庋b的一個 object
中,然后在前一個函數(shù)中返回同樣類型的 object
.
Pipe / Flow
再看我們數(shù)學(xué)公式 z = g(f(m(y)))
屯断,這是個簡單邏輯文虏,如果復(fù)雜點(diǎn): z = i(h(g(f(m(y')))))
等復(fù)雜的嵌套邏輯我們稱之為洋蔥代碼。那能有更簡單靈活的寫法嗎殖演?
pipe
和 flow
是 fp-ts
提供的最常用的簡單化的組合函數(shù)。 pipe
是計(jì)算組合中等到的值年鸳,而 flow
是組合的邏輯趴久,不包括值.
用公式表示:
若 z = g(f(m(y))) = g*f*m(y)
則 pipe = g*f*m(y), flow = g*f*m
用代碼例子:
import { flow, pipe } from 'fp-ts/function';
interface Point {
x: number,
y: number
}
const moveRight5 = (p: Point) => ({ x: p.x - 5, y: p.y });
const moveDown5 = (p: Point) => ({ x: p.x, y: p.y - 5 });
const start = { x: 3, y: 5 };
pipe(start, moveRight5, moveDown5);
pipe(start, flow(moveRight5, moveDown5));
搞定,但并未沒有結(jié)束搔确,因?yàn)榻M合還有一個條件就是可預(yù)測性或者可規(guī)劃性彼棍。
- 可規(guī)劃性,能夠按照既定的規(guī)則
當(dāng)我們在玩高級的托馬斯火車的軌道時膳算,我們時預(yù)制了機(jī)關(guān)的座硕,對于不同的火車經(jīng)過的時候按照火車自己的屬性進(jìn)入不行的路徑,而不改變軌道的配置涕蜂。對應(yīng)到上面的例子华匾,我們只能在 Happy path 下運(yùn)行完成。一旦 start
是個 {}
或者 moveRight5
中出現(xiàn)了異常机隙,這個流程就進(jìn)行不下去了蜘拉。
這個問題我們在下一節(jié)繼續(xù)討論。