λ 演算（英語：lambda calculus，λcalculus）是一套從數學邏輯中發展，以變數繫結和替換的規則，來研究函式如何抽象化定義、函式如何被應用以及遞迴的形式系統。它由數學家阿隆佐邱奇在 20 世紀 30 年代首次發表。lambda 演算作為一種廣泛用途的計算模型，可以清晰地定義什麼是一個可計算函式，而任何可計算函式都能以這種形式表達和求值，它能模擬單一磁帶圖靈機的計算過程；儘管如此，lambda 演算強調的是變換規則的運用，而非實現它們的具體機器。 lambda 演算可比擬是最根本的程式語言，它包括了一條變換規則（變數替換）和一條將函式抽象化定義的方式。因此普遍公認是一種更接近軟體而非硬體的方式。對函數語言程式設計語言造成很大影響，比如 Lisp、ML 語言和 Haskell 語言。在 1936 年邱奇利用 λ 演算給出了對於判定性問題（Entscheidungsproblem）的否定：關於兩個 lambda 運算式是否等價的命題，無法由一個「通用的演演算法」判斷，這是不可判定效能夠證明的頭一個問題，甚至還在停機問題之先。 lambda 演算包括了建構 lambda 項，和對 lambda 項執行歸約的操作。在最簡單的 lambda 演算中，只使用以下的規則來建構 lambda 項： 語法 名稱 描述 x 變數 用字元或字串來表示引數或者數學上的值或者表示邏輯上的值 λxM 抽象化 一個完整的函式定義（M 是一個 lambda 項），在表示式中的 x 都會繫結為變數 x。 M N 應用 將函式 M 作用於引數 N。 M 和 N 是 lambda 項。 產生了諸如：λxλyλzλxzxλyzyx y 的表示式。如果表示式是明確而沒有歧義的，則括號可以省略。對於某些應用，其中可能包括了邏輯和數學的常量以及相關操作。 本文討論的是邱奇的 無型別 lambda 演算，此後，已經研究出來了一些有型別 lambda 演算。 解釋與應用 λ 演算是圖靈完備的，也就是說，這是一個可以用於模擬任何圖靈機的通用模型。 λ 也被用在 λ 表示式和 λ 項中，用來表示將一個變數繫結在一個函式上。 λ 演算可以是有型別或者無型別的，在有型別 λ 演算中（上文所述是無型別的），函式只能在引數型別和輸入型別符合時被應用。有型別 λ 演算比無型別 λ 演算要弱 後者是這個條目的主要部分 因為有型別的 λ 運算能表達的比無型別 λ 演算少；與此同時，前者使得更多定理能被證明。例如，在簡單型別 λ 演算中，運算總是能夠停止，然而無型別 λ 演算中這是不一定的（因為停機問題）。目前有許多種有型別 λ 演算的一個原因是它們被期望能做到更多（做到某些以前的有型別 λ 演算做不到的）的同時又希望能用以證明更多定理。 λ 演算在數學、哲學 Coquand Thierry Type Theory The Stanford Encyclopedia of Philosophy Summer 2013 Edition Edward N Zalta ed、語言學和計算機科學中都有許多應用。它在程式語言理論中佔有重要地位，函數語言程式設計實現了 λ 演算支援。λ 演算在範疇論中也是一個研究熱點。 歷史 作為對數學基礎研究的一部分，數學家阿隆佐邱奇在 20 世紀 30 年代提出了 λ 演算。For a full history see Cardone and Hindleys History of Lambdacalculus and Combinatory Logic 2006 但最初的 λ 演算系統被證明是邏輯上不自洽的 在 1935 年斯蒂芬科爾克萊尼和 J B Rosser 舉出了。 隨後，在 1936 年邱奇把那個版本的關於計算的部分抽出獨立發表 現在這被稱為無型別 λ 演算。 在 1940 年，他創立了一個計算能力更弱但是邏輯上自洽的系統，這被稱為簡單型別 λ 演算。 直到 1960 年，λ 演算與程式語言的關係被確立了；在這之前它只是一個正規化。由於理查德蒙塔古和其他語言學家將 λ 演算應用於自然語言語法的研究，λ 演算已經開始在語言學和計算機科學學界擁有一席之地。Alama Jesse The Lambda Calculus The Stanford Encyclopedia of Philosophy Summer 2013 Edition Edward N Zalta ed 至於為何邱奇選擇 λ 作為符號，連他本人的解釋也互相矛盾：最初是在 1964 年的一封信中，他明確解釋稱這是來源於《數學原理》一書中的類抽象符號（脫字元），為了方便閱讀，他首先將其換成邏輯與符號（land）作為區分，然後又改成形狀類似的 λ。他在 1984 年又重申了這一點，但再後來他又表示選擇 λ 純粹是偶然。 非形式化的直覺描述 在 λ 演算中，每個表示式都代表一個函式，這個函式有一個引數，並且會返回一個值。不論是引數和返回值，也都是一個單參的函式。可以這麼說，λ 演算中只有一種 型別，那就是這種單參函式。函式是透過 λ 表示式匿名地定義的，這個表示式說明了此函式將對其引數進行什麼操作。 例如，加 2 函式 f x x 2 可以用 lambda 演算表示為 λxx 2（或者 λyy 2，引數的取名無關緊要），而 f 3 的值可以寫作 λxx 2 3。函式的應用（application）是左結合的：f x y f x y。 考慮這麼一個函式：它把一個函式作為引數，這個函式將被作用在 3 上：λff 3。如果把這個（用函式作引數的）函式作用於我們先前的 加 2 函式上：λff 3λxx2，則明顯地，下述三個表示式： λff 3λxx2 與 λxx 2 3 與 3 2 是等價的。有兩個引數的函式可以透過 lambda 演算這樣表達：一個單一引數的函式，它的返回值又是一個單一引數的函式（參見柯里化）。例如，函式 f x y x y 可以寫作 λxλyx y。下述三個表示式： λxλyx y 7 2 與 λy7 y 2 與 7 2 也是等價的。然而這種 lambda 表示式之間的等價性，無法找到某個通用的函式來判定。 並非所有的 lambda 表示式都能被歸約至上述那樣的確定值，考慮 λxx xλxx x 或 λxx x xλxx x x 然後試圖把第一個函式作用在它的引數上。λxx x 被稱為 ω 組合子，λxx xλxx x 被稱為 Ω，而 λxx x x λxx x x 被稱為 Ω2，以此類推。若僅形式化函式作用的概念而不允許 lambda 表示式，就得到了組合子邏輯。 動機 在數學和電腦科學中，「可計算的」函式是基礎觀念。對於所謂的可計算性，λ 演算提供了一個簡單明確的語義，使計算的性質可以被形式化研究。λ 演算結合了兩種簡化方式，使得這個語義變得簡單。第一種簡化是不給予函式一個確定名稱，而 匿名 地對待它們。例如，兩數的平方和函式 operatorname square_sumx y x2 y2 可以用匿名的形式重新寫為： x y mapsto x2 y2（理解成一包含和的陣列被對映到 x2 y2） 同樣地， operatorname idx x 可以用匿名的形式重新寫為： x mapsto x（即輸入是直接對應到它本身。） 第二個簡化是 λ 演算只使用單一個引數輸入的函式。如果普通函式需要兩個引數，例如 operatorname square_sum 函式，可轉成接受單一引數，傳給另一個函式中介，而中介函式也只接受一個引數，最後輸出結果。例如， x y mapsto x2 y2 可以重新寫成： x mapsto y mapsto x2 y2 這是稱為柯里化的方法，將多引數的函式轉換成為多個中介函式的複合鏈，每個中介函式都只接受一個引數。 將 operatorname square_sum 函式應用於引數 52，直接產生結果 x y mapsto x2 y25 2 52 22 29 而對於柯里化轉換版的評估，需要再多一步： Bigl bigl x mapsto y mapsto x2 y2bigr5Bigr2 y mapsto 52 y22 在內層表示式中 x 的定義為 5，這就像 β 歸約一樣。 52 22 y 的定義為 2，再次如同 β 歸約。 29 得出相同結果。 lambda 演算 lambda 演算是由特定形式語法所組成的一種語言，一組轉換規則可操作其中的 lambda 項。這些轉換規則被看作是一個等式理論或者一個操作定義。如上節所述，lambda 演算中的所有函式都是匿名的，它們沒有名稱，它們只接受一個輸入變數，柯里化用於實現有多個輸入變數的函式。 lambda 項 lambda 演算的語法將一些表示式定義為有效的 lambda 演算式，而某一些表示式無效，就像 C 程式語言中有些字串有效，有些則不是。有效的 lambda 演算式稱為 lambda 項。 以下三個規則給出了語法上有效的 lambda 項，如何建構的歸納定義： 變數 x 本身就是一個有效的 lambda 項 如果 t 是一個 lambda 項，而 x 是一個變數，則 lambda xt 是一個 lambda 項（稱為 lambda 抽象）； 如果 t 和 s 是 lambda 項，那麼 ts 是一個 lambda 項（稱為應用）。 其它的都不是 lambda 項。因此，lambda 項若且唯若可重複應用這三個規則取得時，才是有效的。一些括號根據某些規則可以省略。例如，最外面的括號通常不會寫入。 lambda 抽象 是指一個匿名函式的定義，它將單一輸入的 lambda xt 替換成 t 的表示式，所以產生了一個匿名函式，它採用 x 的值並返回 t。例如，lambda xx22 是表示使用函式 f x x22 作為 t 項的一個 lambda 抽象。lambda 抽象只是先 設定 了函式定義，還沒使用它。這個抽象在 t 項中綁定了變數 x。一個應用 ts 表示將函式 t 應用在輸入 s，亦即對輸入 s 使用函式 t 產生 t s。 lambda 演算中並沒有變數宣告的概念。如 lambda xxy（即 f x x y）的定義中，lambda 演算將 y 當作尚未定義的變數。lambda 抽象 lambda xx y 在語法上是有效的，並表示將其輸入新增到未知 y 的函式。 可用圓括弧對來消除歧義。例如，lambda xlambda xx x 和 lambda xlambda xx x 表示不同的項（儘管它們剛好化簡到相同值）。這裡第一個例子定義了一個包含子函式的抽象，並將子函式應用於 x（先應用後傳回）的結果；而第二個例子定義了一個傳回任何輸入的函式，然後在應用過程中傳回對輸入為 x 的應用（返回函式然後應用）。 操作函式的函式 在 lambda 演算中，函式被認為是頭等物件，因此函式可以當作輸入，或作為其它函式的輸出返回。 例如，lambda xx 表示對映到本身的函式，x mapsto x 和 lambda xx y 表示將這個函式應用於 y。此外，lambda xy 則表示無論輸入為何，始終返回 y 值的常數函式 x mapsto y。lambda 演算中的函式應用是左結合的，因此 stx 表示 st x。 有幾個 等價 和 化簡 的概念，允許將各個 lambda 項 縮減 為 相同 的 lambda 項。 α 等價 對於 lambda 項，等價的基本形式定義，是 alpha 等價。它捕捉了直覺概念，在 lambda 抽象中一個繫結變數的特別選擇（通常）並不重要。 比如，lambda xx 和 lambda yy 是 alpha 等價的 lambda 項，它們都表示相同的函式（自對映函式）；但如 x 和 y 項則不是 alpha 等價的，因為它們並非以 lambda 抽象方式繫結的。 在許多演示中，通常會確定 alpha 等價的 lambda 項。 為了能夠定義 beta 歸約，需要以下定義： 自由變數 所謂的自由變數是那些在 lambda 抽象不受到繫結的變數。表示式中的一組自由變數定義歸納如下： x 的自由變數就只是 x lambda xt 的自由變數集合，是在 t 中移除了 x 的自由變數集合。 ts 的自由變數是 t 的一組自由變數，與 s 的一組自由變數，這兩項變數的並集。 例如，代表對映自身的 lambda xx，其中的 lambda 項沒有自由變數，但是在函式 lambda xyx 中的 lambda 項，有一個自由變數 y。 避免捕獲的替換記法 假設 t，s 和 r 是 lambda 項，而 x 和 y 是變數。如果寫成 t x r 是一種避免被捕獲的記法方式，表示在 t 這個 lambda 項中，以 r 來替換 x 變數的值。這定義為： x x r r； y x r y，如果 x neq y； tsx r t x rs x r； lambda xtx r lambda xt； 如果 x neq y 而且 y 不在 lambda 項 r 的自由變數中，則 lambda ytx r lambda yt x r。對於 lambda 項 r，變數 y 被稱為是 新鮮 的。 例如，lambda xxy y lambda xx y y lambda xx 和 lambda xy xx y lambda xyx yx x y lambda xy y。 新鮮度條件（要求 y 不在 lambda 項 r 中的自由變數中）對於確保替換不會改變函式的意義很重要。例如，忽視新鮮度條件的替代：lambda xyy x lambda xy y x lambda xx。此替換會將原本意義為常量函式的 lambda xy，轉換成意義為對映自身函式的 lambda xx。 一般來說，在無法滿足新鮮度條件的情況，可利用 alpha 重新命名使用一個合適的新變數來補救，切換回正確的替換概念；比如在 lambda xyy x 中，使用一個新變數 z 重新命名這個 lambda 抽象，獲取 lambda zyy x lambda zy y x lambda zx，則替換就能保留原本函式的義涵。 β 歸約 β 歸約規定了形式如 lambda x t s 的應用，可以化簡成 t x s 項。符號記法 lambda x t s to t x s 用於表示 lambda x t s 經過 β 歸約轉換為 t x s 。例如，對於每個 s，可轉換為 lambda x x s to x x s s 。這表明 lambda x x 實際上的應用是對映自身函式。同樣地，lambda x y s to y x s y ，表明了 lambda x y 是一個常量函式。 lambda 演算可視為函數語言程式設計語言的理想化版本，如 Haskell 或 ML 語言。在這種觀點下，β 歸約對應於一組計算步驟。 這個步驟重複應用 β 轉換，一直到沒有東西能再被化簡。在無型別 lambda 演算中，如本文所述，這個歸約過程可能無法終止， 比如 Omega lambda x xxlambda x xx，是個特殊的 lambda 項。這裡 lambda x xxlambda x xx to xxx lambda x xx x x lambda x xx x x lambda x xx lambda x xxlambda x xx 也就是說，該 lambda 項在一次 β 歸約中化簡到本身，因此歸約過程將永遠不會終止。 無型別 lambda 演算的另一方面是它並不區分不同種類的資料。例如，需要編寫只針對數字操作的功能。然而，在無型別的 lambda 演算中，沒有辦法避免函式被應用於真值、字串或其它非數字物件。 形式化定義 形式化地，我們從一個識別符號（identifier）的可數無窮集合開始，比如 a b c x y z x1 x2 ，則所有的 lambda 表示式可以透過下述以 BNF 正規化表達的上下文無關文法描述： 表示式 識別符號 表示式 λ 識別符號表示式 表示式 表示式 表示式 頭兩條規則用來生成函式，而第三條描述了函式是如何作用在引數上的。通常，lambda 抽象（規則 2）和函式作用（規則 3）中的括弧在不會產生歧義的情況下可以省略。如下假定保證了不會產生歧義：（1）函式的作用是左結合的，和（2）lambda 運算子被繫結到它後面的整個表示式。例如，表示式 λxx xλyy 可以簡寫成 λxx x λyy 。 類似 λxx y 這樣的 lambda 表示式並未定義一個函式，因為變數 y 的出現是自由的，即它並沒有被繫結到表示式中的任何一個 λ 上。一個 lambda 表示式的自由變數的集合是透過下述規則（基於 lambda 表示式的結構歸納地）定義的： 在表示式 V 中，V 是變數，則這個表示式裡自由變數的集合只有 V。 在表示式 λV E 中（V 是變數，E 是另一個表示式），自由變數的集合是 E 中自由變數的集合減去變數 V。因而，E 中那些 V 被稱為繫結在 λ 上。 在表示式 E E 中，自由變數的集合是 E 和 E 中自由變數集合的並集。 例，對於表示式 λxx（我們將第一個 x 視作變數，第二個 x 視作表示式），其中表達式 x 中，由 1，它的自由變數集合是 x，又由 2，表示式 λxx 的自由變數的集合是表示式 x 的自由變數集合減去變數 x。所以對於表示式 λxx，它的自由變數集合是空。 例，對於表示式 λxx x 由形式化描述的第 3 點，我們把它看作 λxxx，λxx 和 x 分別為表示式，由上一例知道 λxx 的自由變數集合為空，表示式 x 的變數集合為變數 x，所以對於 λxx x，它的自由變數集合為 x 與空的並，即 x。 在 lambda 表示式的集合上定義了一個等價關係 在此用 標註，兩個表示式其實表示的是同一個函式 這樣的直覺性判斷即由此表述，這種等價關係是透過所謂的 alpha 變換規則 和 beta 歸約規則。 歸約 歸約的操作包括： 操作 名稱 描述 λxM x λyM y α 轉換 重新命名錶達式中的繫結（形式）變數。用於避免名稱衝突。 λxM E M xE β 歸約 在抽象化的函式定義體中，以參數列達式代替繫結變數。 α 變換 Alpha 變換規則表達的是，被繫結變數的名稱是不重要的。比如說 λxx 和 λyy 是同一個函式。儘管如此，這條規則並非像它看起來這麼簡單，關於被繫結的變數能否由另一個替換有一系列的限制。 Alpha 變換規則陳述的是，若 V 與 W 均為變數，E 是一個 lambda 表示式，同時 E VW 是指把表示式 E 中的所有的 V 的自由出現都替換為 W，那麼在 W 不是 E 中的一個自由出現，且如果 W 替換了 V，W 不會被 E 中的 λ 繫結的情況下，有 λVE λWE VW 這條規則告訴我們，例如 λxλxx x 這樣的表示式和 λyλxx y 是一樣的。 β 歸約 Beta 歸約規則表達的是函式作用的概念。它陳述了若所有的 E 的自由出現在 E VE 中仍然是自由的情況下，有 λVE E E VE 成立。 關係被定義為滿足上述兩條規則的最小等價關係（即在這個等價關係中減去任何一個對映，它將不再是一個等價關係）。 對上述等價關係的一個更具操作性的定義可以這樣獲得：只允許從左至右來應用規則。不允許任何 beta 歸約的 lambda 表示式被稱為 Beta 正規化。並非所有的 lambda 表示式都存在與之等價的正規化，若存在，則對於相同的形式引數命名而言是唯一的。此外，有一個演算法使用者計算正規化，不斷地把最左邊的形式引數替換為實際引數，直到無法再作任何可能的規約為止。這個演算法當且僅當 lambda 表示式存在一個正規化時才會停止。ChurchRosser 定理說明了，當且僅當兩個表示式等價時，它們會在形式引數換名後得到同一個正規化。 η 變換 前兩條規則之後，還可以加入第三條規則，eta 變換，來形成一個新的等價關係。Eta 變換表達的是外延性的概念，在這裡外延性指的是，對於任一給定的引數，當且僅當兩個函式得到的結果都一致，則它們將被視同為一個函式。Eta 變換可以令 lambda x f x 和 f 相互轉換，只要 x 不是 f 中的自由變數。下面說明了為何這條規則和外延性是等價的： 若 f 與 g 外延地等價，即，f a g a 對所有的 lambda 表示式 a 成立，則當取 a 為在 f 中不是自由出現的變數 x 時，我們有 f x g x，因此 lambda x f x lambda x g x，由 eta 變換 f g。所以只要 eta 變換是有效的，會得到外延性也是有效的。 相反地，若外延性是有效的，則由 beta 歸約，對所有的 y 有 λx f x y f y，可得 λx f x f，即 eta 變換也是有效的。 資料型別的編碼 基本的 lambda 演演算法可用於建構布林值，算術，資料結構和遞迴的模型，如以下各小節所述。 lambda 演算中的算術 在 lambda 演算中有許多方式都可以定義自然數，但最常見的還是邱奇數，下面是它們的定義： 0 λfλxx 1 λfλxf x 2 λfλxf f x 3 λfλxf f f x 以此類推。直觀地說，lambda 演算中的數字 n 就是一個把函式 f 作為引數並以 f 的 n 次冪為返回值的函式。換句話說，邱奇整數是一個高階函式 以單一引數函式 f 為引數，返回另一個單一引數的函式。 注意在邱奇原來的 lambda 演算中，lambda 表示式的形式引數在函式體中至少出現一次，這使得我們無法像上面那樣定義 0 在邱奇整數定義的基礎上，我們可以定義一個後繼函式，它以 n 為引數，返回 n 1： SUCC λnλfλxf n f x 加法是這樣定義的： PLUS λmλnλfλxm f n f x PLUS 可以被看作以兩個自然數為引數的函式，它返回的也是一個自然數。你可以試試驗證 PLUS 2 3 與 5 是否等價。乘法可以這樣定義： MULT λmλnm PLUS n 0 即 m 乘以 n 等於在零的基礎上 m 次加 n。另一種方式是 MULT λmλnλfm n f 正整數 n 的前驅元（predecessesor）PRED n n 1 要複雜一些： PRED λnλfλxn λgλhh g f λux λuu 或者 PRED λnn λgλkg 1 λuPLUS g k 1 k λl0 0 注意 g 1λuPLUS g k 1 k 表示的是，當 g 1 是零時，表示式的值是 k，否則是 g k 1。 邏輯與謂詞 習慣上，下述兩個定義（稱為邱奇布林值）被用作 TRUE 和 FALSE 這樣的布林值： TRUE λxλyx FALSE λxλyy 注意 FALSE 等價於前面定義邱奇數零 接著，透過這兩個 λ 項，我們可以定義一些邏輯運算： AND λp qp q FALSE OR λp qp TRUE q NOT λpp FALSE TRUE IFTHENELSE λp x yp x y 我們現在可以計算一些邏輯函式，比如： AND TRUE FALSE λp qp q FALSE TRUE FALSE β TRUE FALSE FALSE λx yx FALSE FALSE β FALSE 我們見到 AND TRUE FALSE 等價於 FALSE。 謂詞 是指返回布林值的函式。最基本的一個謂詞是 ISZERO，當且僅當其引數為零時返回真，否則返回假： ISZERO λnn λxFALSE TRUE 運用謂詞與上述 TRUE 和 FALSE 的定義，使得 ifthenelse 這類語句很容易用 lambda 演算寫出。 有序對 有序對（2 元組）資料型別可以用 TRUE、FALSE 和 IF 來定義。 CONS λx yλpIF p x y CAR λxx TRUE CDR λxx FALSE 連結串列資料型別可以定義為，要麼是為空列表保留的值（egFALSE），要麼是 CONS 一個元素和一個更小的列表。 附加的程式設計技術 lambda 演算出現在相當大量的程式設計習慣用法中，其中許多程式語言最初以 lambda 演算作為語義基礎，在此背景下開發的；有效地利用 lambda 演算作為基底。因為幾個程式語言部份含括了 lambda 演算（或者非常相似的東西），所以這些技術也可以在實際的程式設計中見到，但有可能被認為是模糊或外來的。 命名常數 在 lambda 演算中，函式庫將採用預先定義好的函式集合，其中 lambda 項僅僅是特定的常量。純粹的 lambda 演演算法並不具有命名常數的概念，因為所有的原子 λ 項都是變數；但是在程式主體中，我們可將一個變數當成常量的名稱，利用 lambda 抽象把這個變數繫結，並將該 lambda 抽象應用於預期的定義，來模擬命名常量的作法。因此在 N（主程式 的另一個 lambda 項）中，要以 f 來表示 M（一些明確的 lambda 項），則寫成如下： λfN M 作者經常引入類似如 let 的語法糖，允許以更直觀的次序撰寫上述內容： let f M in N 透過等號連結這個命名常數，即可將 lambda 演算 程式設計 的一個 lambda 項，寫為零或多個函式的定義，而使用構成程式主體的那些函式。這個 let 顯著的限制，是在 M 中並沒有定義 f 名稱，因為 M 不在繫結 f 的 lambda 抽象範疇之內；這意味著遞迴函式定義不能以 let 來使用 M。更進步的 letrec 語法糖允許以直覺的方式編寫遞迴函式定義，而不需用到不動點組合子。 遞迴與不動點 遞迴是使用函式自身的函式定義；在表面上，lambda 演算不允許這樣。但是這種印象是誤解。考慮個例子，階乘函式 f n 遞迴的定義為 f n if n 0 then 1 else nf n1。 在 lambda 演算中，你不能定義包含自身的函式。要避免這樣，你可以開始於定義一個函式，這裡叫 g，它接受一個函式 f 作為引數並返回接受 n 作為引數的另一個函式： g λf nif n 0 then 1 else nf n1。 函式 g 返回要麼常量 1，要麼函式 f 對 n1 的 n 次應用。使用 ISZERO 謂詞，和上面描述的布林和代數定義，函式 g 可以用 lambda 演算來定義。 但是，g 自身仍然不是遞迴的；為了使用 g 來建立遞迴函式，作為引數傳遞給 g 的 f 函式必須有特殊的性質。也就是說，作為引數傳遞的 f 函式必須展開為呼叫帶有一個引數的函式 g 並且這個引數必須再次 f 函式！換句話說，f 必須展開為 g f。這個到 g 的呼叫將接著展開為上面的階乘函式並計算下至另一層遞迴。在這個展開中函式 f 將再次出現，並將被再次展開為 g f 並繼續遞迴。這種函式，這裡的 f g f，叫做 g 的不動點，並且它可以在 lambda 演算中使用叫做悖論運算元或不動點運算元來實現，它被表示為 Y Y 組合子： Y λgλxg x xλxg x x 在 lambda 演算中，Y g 是 g 的不動點，因為它展開為 g Y g。現在，要完成我們對階乘函式的遞迴呼叫，我們可以簡單的呼叫 g Y g n，這裡的 n 是我們要計算它的階乘的數。 比如假定 n 5，它展開為： λnif n 0 then 1 else nY gn1 5 if 5 0 then 1 else 5g Y g，51 5g Y g 4 5λnif n 0 then 1 else nY gn1 4 5if 4 0 then 1 else 4g Y g，41 54g Y g 3 54λnif n 0 then 1 else nY gn1 3 54if 3 0 then 1 else 3g Y g，31 543g Y g 2 等等，遞迴的求值演算法的結構。所有遞迴定義的函式都可以看作某個其他適當的函式的不動點，因此，使用 Y 所有遞迴定義的函式都可以表達為 lambda 表示式。特別是，我們現在可以明晰的遞迴定義自然數的減法、乘法和比較謂詞。 標準化的組合子名稱 某一些 lambda 項有普遍接受的名稱： I λxx K λxλyx S λxλyλzx z y z B λxλyλzx y z C λxλyλzx z y W λxλyx y y U λxλyy x x y ω λxx x Ω ω ω Y λgλxg x x λxg x x 其中有幾個在 消除 lambda 抽象 中有直接的應用，將 lambda 項變為組合演算的術語。 消除 lambda 抽象 如果 N 是一個沒有 λ 抽象的 lambda 項，但可能包含了命名常量（組合子），則存在一個 lambda 項 T xN，這相同於一個缺少 λ 抽象（除了作為命名常量的一部份，如果這些被認為是非原子的）的 λxN；也可以被視為匿名變數，就如同 T xN 從 N 之中刪除所有出現的 x，同時仍然允許在 N 包含 x 的位置替換引數值。 轉換函式 T 可由下式定義： T x x I T x N K N if x is not free in N T x M N S T x M T x N 在這兩種情況下，形式 T xN P 可藉由使初始的組合子 I，K 或 S 獲取引數 P 而化簡， 就像 λxN P 經過 β 歸約一樣。I 返回那個引數。K 則將引數拋棄，就像 λxN，如果 x 在 N 中不是以自由變量出現。S 將引數傳遞給應用程式的兩個子句，然後將第一個結果應用到第二個的結果之上。 組合子 B 和 C 類似於 S，但把引數傳遞給應用的一個子項（B 傳給 引數 子項，而 C 傳給 函式 子項），如果子項中沒有出現 x，則儲存後續的 K。與 B 和 C 相比，S 組合子實際上混合了兩個功能： 重新排列引數，並複製一個引數，以便它可以在兩個地方使用。W 組合子只做後者，產生了 SKI 組合子演算的 B，C，K，W 系統。 可計算函式和 lambda 演算 自然數的函式 F N N 是可計算函式，當且僅當存在著一個 lambda 表示式 f，使得對於 N 中的每對 x y 都有 F x y 當且僅當 f x y，這裡的 x 和 y 分別是對應於 x 和 y 的邱奇數。這是定義可計算性的多種方式之一；關於其他方式和它們的等價者的討論請參見邱奇 圖靈論題。 lambda 演算與程式語言 匿名函式 比如計算平方的函式 square 在 Lisp 中可以表示為如下的 lambda 表示式 lambda x x x 符號 lambda 建立一個匿名函式，給定引數列表 x ，以及一個作為函式體的表示式 x x。 匿名函式有時稱為 lambda 表示式。 很多命令式語言都有函式指標或者類似的機制。但是函式指標並不是型別中的一等公民，函式是一等公民當且僅當函式可以在執行時建立。 下面一些語言支援函式的執行時建立： Smalltalk、 JavaScript、 Kotlin、 Scala、 Python3、 C delegates、 C11 等。 化簡策略 關於複雜度的註釋 並行與並發 參見 邱奇 圖靈論題 遞迴函式 可計算函式 柯里化 參考文獻 外部連結 LAllison Some executable λcalculus examples Georg PLoczewski The Lambda Calculus and A To Dissect a Mockingbird A Graphical Notation for the Lambda Calculus with Animated Reduction 人物介紹 神奇的 λ 演算 譯 The Y combinator Slight Return Λ 運算淵源介紹 Category 計算模型 Category 遞迴論