map
是 FP 最具代表性的 Higher Order Function,僅管大部分 FP 原則都沒搞得很懂,但 map
一定都用得很熟;大部分人都將 map
用在 Array,但因為 First Class Function,map
也能將兩個 Function 綁定。
Version
Ramda 0.27.1
Imperative
let f = x => -(x + 1)
f (1) // ?
f
將兩個 argument 相加並取負號,可使用 +
與 -
operator 實現。
這個 function 就功能而言 100% 沒問題,但能否更進一步 Point-free 呢 ?
pipe
import { pipe, inc, negate } from 'ramda'
pipe (inc, negate) (1) // ?
直覺會使用 pipe
組合 inc
與 negate
。
compose
import { compose, inc, negate } from 'ramda'
compose (negate, inc) (1) // ?
既然能用 pipe
就能使用 compose
,pipe
是 由左到右
執行,而 compose
是 由右向左
執行。
map
import { map, inc, negate } from 'ramda'
map (negate, inc) (1) // ?
跟 compose
寫法長得好像喔,只是將 compose
換成 map
,難道 map
等於 compose
?
map
Functor f => (a → b) → f a → f b
傳入 unary function 改變 Functor 內部 value
這是 map
的定義,注意 Ramda 從來都沒說第二個 argument 是 Array,而是說它是個 Functor。
Array 是 Functor,function 也是 Functor,所以也能將 function 用在 map
。
簡單來說,支援
map
的 Object 就是 Functor,而 function 本身就是一種 mapping,所以 function 可以視為 Functor
使用 map
將 inc
與 negate
綁定相當於使用 compose
對 inc
與 negate
組合。
事實上在 map 官網,最後一句話就是
Also treats functions as functors and will compose them together.
,只可惜微言大意,並沒有更進一步的範例,因此很容易忽略
Conclusion
pipe
是由左向右
,而compose
是由右向左
,兩者可等價替換- 若只
compose
兩個 function,可等價使用map
替換,因為 function 也是 Functor,使用map
將兩個 function 綁定,等效於使用compose
組合兩個 function