Either 適合 Function Pipeline,可提早結束讓後續 Pure Function 不執行,但若 Pure Function 也回傳 Either,則會產生 Nested Either,如此必須使用 chain
取代 map
。
Version
Sanctuary 3.1.0
add
import { pipe, Left, Right, map, add } from 'sanctuary'
let div = x => y =>
y === 0 ?
Left ('Can not divide by zero') :
Right (x / y)
let f = x => pipe ([
div (x),
map (add (1))
])
f (2) (0) // ?
f (2) (1) // ?
f (3) (1) // ?
第 8 行
let f = x => pipe ([
div (x),
map (add (1))
])
div
回傳 Either,但 add
只是回傳 Number,此時簡單使用 map
組合 add
即可。
Either
import { pipe, map, Left, Right } from 'sanctuary'
let div = x => y =>
y === 0 ?
Left ('Can not divide by zero') :
Right (x / y)
let add = x => y =>
y === 2 ?
Left ('Can not add by 2') :
Right (x + y)
let f = x => pipe([
div (x),
map (add (1))
])
f (2) (0) // ?
f (2) (1) // ?
f (3) (1) // ?
第 8 行
let add = x => y =>
y === 2 ?
Left ('Can not add by 2') :
Right (x + y)
沒有使用 Sanctuary 提供的 add
,自行實作回傳 Either 的 add
。
此特殊版本的 add
無法處理 +2
會發出 Exception,因此改回傳 Either。
13 行
let f = x => pipe([
div (x),
map (add (1))
])
一樣使用 map
組合 add
。
當改用回傳 Either 的 add
時,會發現結果出現 Nested Either,這並不是我們想要的。
chain
import { pipe, Left, Right, chain } from 'sanctuary'
let div = x => y =>
y === 0 ?
Left ('Can not divide by zero') :
Right (x / y)
let add = x => y =>
y === 2 ?
Left ('Can not add by 2') :
Right (x + y)
let f = x => pipe ([
div (x),
chain (add (1))
])
f (2) (0) // ?
f (2) (1) // ?
f (3) (1) // ?
13 行
let f = x => pipe ([
div (x),
chain (add (1))
])
由 map
改成 chain
。
由 map
改成 chain
後,就不會出現 Nested Either。
Either Chain
import { pipe, Left, Right, map, chain } from 'sanctuary'
let div = x => y =>
y === 0 ?
Left ('Can not divide by zero') :
Right (x / y)
let add = x => y =>
y === 2 ?
Left ('Can not add by 2') :
Right (x + y)
let mul = x => y =>
y === 4 ?
Left ('Can not multiply by 4') :
Right (x * y)
let f = x => pipe([
div (x),
chain (add (1)),
chain (mul (2)),
])
f (2) (0) // ?
f (2) (1) // ?
f (3) (1) // ?
f (4) (1) // ?
13 行
let mul = x => y =>
y === 4 ?
Left ('Can not multiply by 4') :
Right (x * y)
也自行實作回傳 Either 的 mul
,此版本無法處理 *4
會發出 Exception。
18 行
let f = x => pipe([
div (x),
chain (add (1)),
chain (mul (2)),
])
遇到會回傳的 Either 的 function,只要由 map
改用 chain
即可。
Conclusion
- 若要組合一般 function,使用
map
即可;若要組合回傳 Either 的 function,則要使用chain