Haskell 支援 First Class Function,所以可將各 Function 相同部分抽成 Higher Order Function,不同部分亦抽成小 Function,最後以 Argument 傳入產生各 Function。
Version
Haskell for Mac 1.8.2
Named Function
ifEvenInc x =
if even x
then x + 1
else x
ifEvenDouble x =
if even x
then x * 2
else x
ifEvenSquare x =
if even x
then x ^ 2
else x
ifEvenInc 4
ifEvenDouble 4
ifEvenSquare 4
我們有 ifEvenInc
、ifEvenDouble
與 ifEvenSquare
三個 function ,都判斷 parameter 是否為偶數,若是則執行不同 expression,否則都回傳原來值。
我們發現這三個 function 非常類似,唯一差別只有 parameter 為偶數時的回傳不同 expression。
even
為 Haskell 內建 function,可直接使用
Higher Order Function
inc x = x + 1
double x = x * 2
square x = x ^ 2
ifEven f x =
if even x
then f x
else x
ifEvenInc x = ifEven inc x
ifEvenDouble x = ifEven double x
ifEvenSquare x = ifEven square x
ifEvenInc 4
ifEvenDouble 4
ifEvenSquare 4
可將不同 expression 單獨抽出來成為 function,ifEven
的第一個 argument 以 function 傳入。
Point-free
inc x = x + 1
double x = x * 2
square x = x ^ 2
ifEven f x =
if even x
then f x
else x
ifEvenInc = ifEven inc
ifEvenDouble = ifEven double
ifEvenSquare = ifEven square
ifEvenInc 4
ifEvenDouble 4
ifEvenSquare 4
可發現 ifEvenInc
與 ifEven
最後一個 argument 都是 x
,可同時兩邊消去 x
,使 ifEven
改回傳 function。
只有 curry function 才允許
=
兩邊相同 argument 消去
Lambda Function
ifEven f x =
if even x
then f x
else x
ifEvenInc = ifEven (\x -> x + 1)
ifEvenDouble = ifEven (\x -> x * 2)
ifEvenSquare = ifEven (\x -> x ^ 2)
ifEvenInc 4
ifEvenDouble 4
ifEvenSquare 4
除了 named function 外,對於只使用一次的 function,亦可使用 lambda function 取代。
Conclusion
- 由本文可發現 Haskell 定義 curry function 與呼叫 function 都使用 space 的方便,當
=
左右兩側的 argument 相同時,可以很直覺的發現並消去 - 還可發現 curry function 的妙用,對於重構成 higher order function 的直覺與方便,這也是為什麼 FP 預設都使用 curry function