更優雅的方式產生 function

FP 既然強調 Higher Order Function,就會希望 argument 以 function 傳入,因此就會有 function 能夠傳回 function 的需求,除了回傳 Anonymous Function 或 Lambda Expression 外,F# 更提供了 Partial Function Application ,讓程式碼更優雅。

Version


macOS High Sierra 10.13.3
.NET Core SDK 2.1.101
Rider 2017.3.1
F# 4.1

Lambda Expression


舉一個最簡單的例子

1
2
[1..5]
|> List.iter (fun i -> printfn "%d" i)

15List 全部印出來。

artial00

List.iter() 的 argument 要求 'T -> unit 的 function。

在沒有提供 Partial Function Application 的程式語言,我們會傳進 Anonymous function 或 Lambda Expression。

1
fun i -> printfn "%d" i

這種寫法中規中矩,儘管語法不太一樣,在一般語言都看得到。

Partial Function Application


1
2
[1..5]
|> List.iter (printfn "%d")

既然 List.iter() 的 argument 要求 'T -> unit 的 function,我們只要能產生 T -> unit 就符合 List.iter() 的需求。

printfn() 的 singnature 為 string -> 'T -> unit,他的意思是:

  • 當傳入兩個參數為 string'T 時,回傳值為 unit
  • 當傳入一個 參數為 string 時,回傳值回 T -> unit

List.iter() 要的正是 'T -> unit,所以我們只要傳入一個參數即可。

1
printfn "%d"

這種寫法是不是比 Lambda Expression 更優雅呢?

Summary


  • 在多參數的 function,只要提供 部分參數,就會回傳一個新的 function,而不必自己建立 Anonymous Function 或 Lambda Expression。
  • 在多參數的 function,其型別是以 -> 隔開,如 string -> 'T -> unit,而不是 string, 'T -> unit,因為 F# 的 function 可隨時提供 部分參數,而回傳新的 function,如只提供 string,就會回傳 'T -> unit,這也是為什麼 F# 在每個參數間以 -> 隔開,而非 ,

Conclusion


  • Partial Function Application 並不是 F# 的獨門絕技,只要是 FP 語言都會有,算是 FP 語言的基本要求,但在一般語言如 C#、JavaScript 卻看不到,只能使用 Lambda Expression / Anonymous Function / Arrow Function 來處理,但 Partial Function Application 提供了更優雅的方式
2018-04-03