柯里化的前生今世(一):函數面面觀

關於

本文作為開篇,介紹了出場人物,並形象化的引入了高階函數,

得到了柯里化的概念。

後續文章,會介紹高階函數的實現方式,詞法作用域和閉包,參數化類型,類型上的柯里化,

敬請期待。

註:由於某些不可名狀的歷史原因,寫作目的居然放在了第四篇末尾「關於寫作意圖」一節。。

所以,如果你想知道我為什麼要寫這些東西,請參考第四篇。。

來跟我一起穿越過去。。

哈哈,不想多說了。。哈哈,讓我再笑一會。。 _(:зゝ∠)_

人物介紹

球星庫里

庫里,Stephen Curry,1988年3月14日出生於美國俄亥俄州阿克倫(Akron, Ohio),

美國職業籃球運動員,司職控球後衛,效力於NBA金州勇士隊。

斯蒂芬·庫里2009年通過選秀進入NBA後一直效力於勇士隊,新秀賽季入選最佳新秀第一陣容;

2014-15賽季隨勇士隊獲得NBA總冠軍;

兩次當選常規賽MVP,兩次入選最佳陣容第一陣容,三次入選全明星賽西部首發陣容。

Haskell Curry

這次我們說的不是NBA的庫里,而是美國著名的數學家,邏輯學家Haskell Curry,它在組合子邏輯方面有傑出貢獻。

Curry本科就讀於哈佛大學醫學專業,業餘選修了數學,1917年轉到了數學系。

畢業後,在通用電氣找到了一份電氣工程師工作,繼續在麻省理工進修電氣工程,但意識到自己更適合做理論研究,而非應用科學。

1922年轉專業到了物理學,但物理學哈佛會更好些,於是作為助教回到了哈佛,1924年拿到了物理碩士學位。

隨後,在哈佛攻讀數學博士學位。

1924年,他最開始的研究方向是微分方程理論,與此同時他接觸了一些邏輯學。

閱讀了羅素和懷特海的《數學原理》之後,他產生了使用組合子來分析代換規則的設想。

於是,放棄了微分方程的研究,準備撰寫一篇邏輯方面的博士論文。

1929年,他的第一篇論文《邏輯代換的分析》在《美國數學報》發表。

之後,Curry在賓夕法尼亞大學擔任教員直至1966年退休,期間曾擔任國家研究委員,普林斯頓的高級學會會員。

發表的論文包括,《組合子邏輯的全稱量詞》《組合子理論的補遺》《顯式變數的組合邏輯觀點》《組合邏輯中相等性及推導的幾個性質》。

1942年,Curry作為符號邏輯學會會長,發表了離職演說《數理邏輯的組合子基礎》。

Curry闡明了組合子邏輯與Chruch的lambda演算之間的密切聯繫,

建立了一套類似於Church和Rosser的完備系統。

第二次世界大戰期間,Curry又開始研究應用數學,1943年發表了《Heaviside演算》。

1946年,Curry在應用物理實驗室工作後,去了阿伯丁實驗場,發布了《使用ENIAC的逆向插值法研究》和《使用ENIAC的四階插值法研究》。

主要著作有,《組合邏輯》和《數理邏輯基礎》。

註:這裡說的這麼仔細,是有原因的。組合子邏輯和lambda演算 ,我們多多少少也會提到。

柯里化

名字的由來

以下是維基百科關於Currying的定義:

In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument.

Currying這個概念,首先是由Gottlob Frege引入的,以邏輯學家Haskell Curry命名。

雖然,這個概念是Moses Sch?nfinkel發明的。

表達式的值和類型

為了說明Currying我們先引入類型的概念。

我們知道編程語言中的表達式是有值的,我們常說,表達式的值為1,值為a

他們在內存中的存儲方式是一樣的,都是二進位方式。

但是,感覺上,他們應該是不同的東西,於是,我們用不同的類型加以區分。

我們稱值1的類型是Int,整型,

a的類型是Char,字元型。

於是,我們就在值的概念上建立了一層抽象,不同的值因此有了不同的屬性。

用數學語言來說,類型作為值集上的一種等價關係,誘導出了對該值集的一種劃分,

相同類型的值構成了一個等價類。

註:我們後面將會看到函數類型的引入,讓事情變得不是這麼簡單了。

函數面面觀

函數用來將一個或多個值變成另一個值,函數也是一種值,它同樣具有類型。

例如,加法函數add是把兩個整型值變成一個整型值,假如我們已經定義好了add函數,我們可以這樣調用它。

註:我們這裡使用的編程語言,函數調用是不用加括弧的,具有最高優先順序。add 1 2類似於add(1,2)

add 1 2= 3

現在我們考慮一個問題,如果我們只給add提供一個參數,結果是什麼呢?

即,add 1是什麼?

我們可以形象化的這樣考慮,先考慮add

add就像一台有兩個插槽的機器,

如果兩個插槽分別提供了12,那麼它會彈出結果3

問,如果只有一個插槽提供了1,那它是什麼?

很顯然,它還是一台機器,只不過只有一個插槽罷了。

因此,add 1還是一個函數,只不過它只接受一個參數罷了,

它返回參數值加1的結果,它的類型我們可以記為,

add 1 :: Int -> Int

我們再回過頭來考慮add的類型,我們看到,

add接受1作為參數,返回add 1這個函數。

因此,我們對add就有另外一種看法了,

它是一台有一個插槽的機器,接受參數1後,

彈出的結果是另一台有一個插槽的機器add 1

因此add的類型我們可以記為,

add :: Int -> (Int -> Int)

為了書寫方便,我們假定->具有右結合律,因此,

add :: Int -> Int -> Int

高階函數

事實上,Currying指的是這樣的一個高階函數,

curry :: ((a, b) -> c) -> (a -> b -> c)

它把函數f變成函數g

f :: ((a, b) -> c)g :: a -> b -> cg = curry ff = uncurry g

使得任意的x,y,滿足,

f (x, y) = g x y


參考

柯里生平

Haskell Curry

Currying

Currying - HaskellWiki

推薦閱讀:

Coq學習筆記11:策略和證明自動化
我願意在她手掌之中(一):範式
持久化數據結構學習筆記——序列
函數式編程,Haskell,範疇論的關係

TAG:函數式編程 | 編程語言 |