點燈坊

失くすものさえない今が強くなるチャンスよ

Haskell 之 Function Pipeline

Sam Xiao's Avatar 2021-06-06

Haskell 提供多種 Operator 組合 Function,可視需求與可讀性選擇使用。

Version

Haskell for Mac 1.8.2

map()

f x = map(*2)(map(+1) x)

f [1, 2, 3]

若要使 List 的每個 element 先 +1,最後再加 *2,可直接搭配兩次 map() 完成。

pipe000

$

f x = map(*2) $ map(+1) x

f [1, 2, 3]

傳統 Function Composition 會造成 () 爆炸,Haskell 提供了 $,則無論多少層 f(x) 都只有一層 $

pipe001

&

import Data.Function

f x = x & map(+1) & map(*2)

f [1, 2, 3]

若你覺得 $由右至左 不易閱讀,而想 由左至右,可改用 Data.Function&

pipe002

.

f = map(*2) . map(+1)

f [1, 2, 3]

若想使 f() 能 Point-free,可使用 .map(+1)map(*2) 加以組合,唯 .由右至左

pipe003

>>>

import Control.Category

f = map(+1) >>> map(*2)

f [1, 2, 3]

若你覺得 .由右至左 不易閱讀,而想 由左至右,可改用 Control.Category>>>

pipe004

Composition Law

import Control.Category

transform = (+1) >>> (*2)

f = map transform

f [1, 2, 3]

List 是 Functor,因此遵循 composition law:

fmap f . fmap g = fmap (f . g)

第 3 行

transform = (+1) >>> (*2)

因此可將 (*2)(+1) 使用 >>> 組合起來成 transform()

第 5 行

f = map transform

最後只要使用一次 map() 即可。

comp005

Conclusion

  • Haskell 的 & 相當於 F# 的 |>
  • Haskell 的 . 相當於 Ramda 的 compose(),而 >>> 相當於 Ramda 的 pipe()