在本系列文中,所有的程式碼都可以在 should-i-use-fp-ts 找到,今日的範例放在 src/day-23
並且有測試可以讓大家練習。
平常大家很長使用的 Array.Prototype
的函式也有很多是 functional programming
的特性,而這些函式也可以使用 Array
ADT 來進行撰寫。
const sumNormal = (xs: Array<number>) =>
xs
.map(x => x + 1)
.filter(x => x % 2 === 0)
.reduce((acc, x) => acc + x, 0);
const sumFp = (xs: Array<number>) => pipe(
xs,
A.map(x => x + 1),
A.filter(x => x % 2 === 0),
A.reduce(0, (acc, x) => acc + x),
);
大家可能會想,這樣有什麼作用?為什麼需要再重新發明一次這些 function?
差異有以下:
Array.Prototype
是基於 Array instance
,之後傳入運算的函式,而Array ADT
則是先傳入運算式,而後接收實體,這樣就可以使用 pipe 之類的 compose function 來進行組合。我們使用 Array
以及 Array ADT
來分別製作 head
函式。
// (xs: Array<number>) => number
const headNormal = (xs: Array<number>) => xs[0];
// (xs: Array<number>) => Option<number>
const headFp = (xs: Array<number>) => pipe(
xs,
A.head,
);
大家可以發現,兩個參數的輸出並不一樣,為什麼?
因為 Array ADT
的實作,保證了 type safety,如果對於一個空陣列,兩個 head function 分別會輸出什麼?
headNormal([]); => undefined
headFp([]); => { _tag: 'None'}
headNormal
的型別並沒有提到任何可能會輸出 undefined
的資訊,而 head
則有考慮到失敗的可能性,這樣才是真正有 type safety
的函數。
今天的主題在 should-i-use-fp-ts 在 src/day-23
並且有測試可以讓大家練習。