當引入 Maybe 後,若 Function 會回傳 Maybe,則適當使用 traverse
或 justs
將使 Function Pipeline 更為順暢。
Version
Sanctuary 3.1.0
traverse
import { pipe, compose, Maybe, ifElse, Just, Nothing, K, equals, gte, mult, map, traverse, join, justs, maybe, mean, I } from 'sanctuary'
let data = [[2, 4, 5], [6, 0, 7], [1, 3, 8]]
let score = ifElse
(equals (0))
(K (Nothing))
(ifElse
(gte (5))
(compose (Just) (mult (2)))
(Just))
pipe ([
map (traverse (Maybe) (score)),
justs,
join,
mean,
maybe (0) (I)
]) (data) // ?
第 3 行
let data = [[2, 4, 5], [6, 0, 7], [1, 3, 8]]
每個 Array 代表一個人 3 局的得分數,共有 3 人參賽,其計分規則如下:
- 若有人其中一局為
0
分,則該人分數都不列入計算 - 若該局分數大於
5
分,則分數乘以2
倍
最後求出每局平均分數。
第 5 行
let score = ifElse
(equals (0))
(K (Nothing))
(ifElse
(gte (5))
(compose (Just) (mult (2)))
(Just))
使用 ifElse
組合 score
:
由於若有人其中一局為 0
分則不列入計算,因此 score
決定回傳 Nothing:
K (Nothing)
:若分數為0
則回傳 Nothingcompose (Just) (mult (2))
:若分數大於5
則成以2
回傳 JustJust
:若分數小於5
則只回傳 Just
13 行
pipe ([
map (traverse (Maybe) (score)),
justs,
join,
mean,
maybe (0) (I)
]) (data) // ?
使用 pipe
組合 f
:
map (traverse (Maybe) (score))
:- 由於傳入為 Array Array,
map
是應付最外層map
- 對於內層 Array,原本應該使用
map (score)
,但因為score
回傳 Maybe,因此內層為 Array Maybe - 考慮將配合外層 Array 將 Nothing 忽略,因此改用
traverse (Maybe)
將內層轉為 Maybe Array - 最後結果為 Array Maybe Array
- 由於傳入為 Array Array,
justs
:從 Array Maybe 忽略 Nothing,並解開 Just,回傳 Array Arrayjoin
:將 Array Array 攤平成一層 Arraymean
:從 Array 計算出平均值,但mean
回傳 Maybemaybe (0) (I)
:解開 Maybe
Conclusion
- 因為需求是
0
分不列入計算,因此適合使用justs
忽略 Nothing justs
會將 Array Maybe 中的 Nothing 忽略,因此特別使用traverse
將內層 Array Maybe 轉成 Maybe Array,才可配合外層形成 Array Maybe