F 函式式程式設計之 柯里化 currying

2022-07-11 10:21:12 字數 1741 閱讀 3951

即使沒有專門學習過函式式的人也有可能聽說過傳說中的柯里化(currying),這是乙個比較 「出圈」 的概念,也是函式式程式設計的重要特性之一。

我會從最簡單的情況開始講述,剛開始你可能覺得無聊,但隨著函式的演化,事情會開始變得有趣。

下面請看乙個正常的 f# 函式:

let add x y = x + y

let three = add 1 2

上面這個 add 函式共有兩個引數 x 和 y,如果呼叫函式時給齊引數,它返回計算結果,如上所示,第一行定義了乙個函式 add, 第二行餵給它兩個引數 1 和 2, 它返回計算值 3

所謂柯里化,就是當呼叫該函式時我們只給它乙個引數,它就返回另乙個函式,像這樣:

let add1 = add 1

let three = add1 2

如上所示,我們給餵給 add 乙個引數(整數 1),它自然無法完成計算,如果是普通的命令式程式設計,這樣做會報錯,但在函式式裡,則會返回乙個新的函式 add1, 函式 add 缺少的那乙個引數就是 add1 的引數。

add 的型別是int -> int -> int(前兩個 int 是引數,最後乙個 int 是返回值)

add1 的型別是(int -> int)(是乙個函式)

如果給 add1 喂引數 2,此時引數齊了,會返回計算結果 3

另外,還可以這樣操作:

let addx x = add x

let add1 = addx 1

let three = add1 2

在上面的**中, addx 的型別是int -> (int -> int), 意思是 addx 這個函式接受乙個引數 int, 返回值是乙個函式(int -> int)

事情開始變得有趣了,還可以這樣操作:

let add x y = x + y

let addx x = add x

let addxy x y = addx x y

let three = addxy 1 2

addxy 的型別(函式簽名)是 int -> int -> int (正好與 add 的簽名一模一樣)

已知addxy x y = addx x y, 同時已知addx x = add x, 可得addxy x y = add x y

這正是 addxy 的簽名與 add 的簽名一模一樣的原因,他們的計算結果也是一樣的。

故事還沒有結束,下面繼續演化,是更有趣的事情。

在普通的命令式程式設計裡,加號+是乙個運算子,但在 f# 裡,加號+本質上是乙個函式!而x + y其實是(+) x y的語法糖!

也就是說,當我們寫下這句let add x y = x + y, 事實上等於寫了let add x y = (+) x y

仔細觀察,不難發現,我們自己定義的函式add, 與 f# 自帶的函式(+)是一模一樣的。

本文到此結束,從最常見的情形出發,經過簡單而曲拆的柯里化變換之後,我們又回到了最初的地方,但經過這一小段旅程,我相信你和我一樣,再看同一行**,會有一種透過表象看到本質的感覺。

函式式程式設計之柯里化(curry)

函式式程式設計curry的概念 只傳遞給函式一部分引數來呼叫函式,然後返回乙個函式去處理剩下的引數。var add function x var increment add 1 increment 1 2 var addten add 10 addten 10 20 我們可以一次性的呼叫函式,也可以...

js函式式程式設計之柯里化(curry)

curry概念 只傳遞給函式一部分引數來呼叫它,讓它返回乙個函式去處理剩下的引數。你可以一次性地呼叫curry函式,也可以每次只傳乙個引數分多次呼叫。var add function x var increment add 1 var addten add 10 increment 2 3 addt...

Scala函式式程式設計 Curry柯里化

函式式程式設計的乙個思想 只傳遞給函式一部分引數來呼叫函式,然後返回乙個函式去處理剩下的引數。簡單說curry就是對高階函式 就是一種對過程的抽象 參考map它就是乙個抽象的過程 的降階處理。比如 function arg1,arg2 變成function arg1 arg2 function ar...