若要以 Function Pipeline 處理 Rejected,可使用多個 mapRej
,不像 Promise 只能使用一個 otherwise
。
Version
Fluture 14.0.0
mapRej
import { create, env } from 'sanctuary'
import { reject, fork, map, mapRej } from 'fluture'
import { env as flutureEnv } from 'fluture-sanctuary-types'
import { error, log } from 'wink-fp'
let { pipe } = create ({ checkTypes: true, env: env.concat (flutureEnv) })
let data = reject (1)
pipe ([
map (x => x + 1),
mapRej (x => x + 2),
fork (error) (log)
]) (data)
data
為 Rejected,儘管在 pipe
中同時有處理 Resolved 的 map
,亦有處理 Rejected 的 mapRej
,整個 Function Pipeline 會無視 map
,只執行 mapRej
。
mapRej :: (a -> c) -> Future a b -> Future c b
將 Rejected 與一般 function 綁定並回傳新 Rejected
a -> c
:一般 function
Future a b
:data 為 Future
Future c b
:回傳新 Future
mapRej
為 Future 專屬 function,因此只支援 Future,不像map
是支援 Functor
Function Pipeline
import { create, env } from 'sanctuary'
import { reject, fork, map, mapRej } from 'fluture'
import { env as flutureEnv } from 'fluture-sanctuary-types'
import { error, log } from 'wink-fp'
let { pipe } = create ({ checkTypes: true, env: env.concat (flutureEnv) })
let data = reject (1)
pipe ([
map (x => x + 1),
mapRej (x => x + 2),
mapRej (x => -x),
fork (error) (log)
]) (data)
mapRej
最可貴的是回傳 Rejected,這讓 Rejected 也能使用多個 mapRej
完成 Function Pipeline。
Ramda 的 otherwise
會回傳 Resolved,這使得整個 Function Pipeline 中只能使用一個 otherwise
,若要使用 Function Pipline 處理 Rejected,只能另外抽 function 再傳入 otherwise
,而不能如 Future 一樣在一個 Function Pipeline 同時處理 Resolved 與 Rejected。
Point-free
import { create, env } from 'sanctuary'
import { reject, fork, map, mapRej } from 'fluture'
import { env as flutureEnv } from 'fluture-sanctuary-types'
import { error, log } from 'wink-fp'
let { pipe, add, negate } = create ({ checkTypes: true, env: env.concat (flutureEnv) })
let data = reject (1)
pipe ([
map (add (1)),
mapRej (add (2)),
mapRej (negate),
fork (error) (log)
]) (data)
map
與 mapRej
的 callback 可傳入 add
與 negate
使其 Point-free。
Composition Law
import { create, env } from 'sanctuary'
import { reject, fork, map, mapRej } from 'fluture'
import { env as flutureEnv } from 'fluture-sanctuary-types'
import { error, log } from 'wink-fp'
let { pipe, add, negate } = create ({ checkTypes: true, env: env.concat (flutureEnv) })
let data = reject (1)
let t = pipe ([
add (2),
negate
])
pipe ([
map (add (1)),
mapRej (t),
fork (error) (log)
]) (data)
Future 也是 Functor,因此支援 composition law,可將 mapRej
的 callback 都以 pipe
組合成 t
再一次傳入 map
。
Railway Oriented Programming
mapRej
支援 Railway Oriented Programming,因為傳入一般 function,回傳仍然是 Rejected Future,因此繼續留在 Rejected Track,不會切到 Resolved Track。
Conclusion
- Promise 只能在同一個 Function Pipeline 中使用一次
otherwise
,而 Future 可使用多次mapRej
,這使得 Future 可在同一個 Function Pipeline 中處理 Rejected Future 與 Resolved Future
Reference
Aldwin Vlasbolm, Functional Alternative to Promises
Fluture, mapRej