| 各種函數 |
| --- |
| *x* ↦ *f* (*x*) |
| 
不同定義域和陪域 |
| 
* {\displaystyle X} → {\displaystyle \mathbb {B} }, {\displaystyle \mathbb {B} } → {\displaystyle X}, {\displaystyle \mathbb {B} ^{n}} → {\displaystyle \mathbb {B} }
* {\displaystyle X} →（英语：） {\displaystyle \mathbb {Z} }, {\displaystyle \mathbb {Z} ^{+}}→ {\displaystyle X}
* {\displaystyle X} →（英语：） {\displaystyle \mathbb {R} }, {\displaystyle \mathbb {R} } → {\displaystyle X}, {\displaystyle \mathbb {R} ^{n}} →（英语：） {\displaystyle X}
* {\displaystyle X} →（英语：） {\displaystyle \mathbb {C} }, {\displaystyle \mathbb {C} } → {\displaystyle X}, {\displaystyle \mathbb {C} ^{n}} →（英语：） {\displaystyle X}

 |
| 函數類/性質 |
| 
* 常值
* 恆等
* 線性
* 多項式
* 有理
* 代數
* 解析
* 光滑
* 連續
* 可測
* 單射
* 满射
* 双射

 |
| 
構造 |
| 
* 限制
* 複合
* λ
* 逆

 |
| 
推廣 |
| 
* 偏（英语：）
* 多值
* 隱

 |
| * 
* 论
* 编
 |

**λ演算**（英語：lambda calculus，λ-calculus）是一套從數學邏輯中發展，以變數綁定和替換的規則，來研究函式如何抽象化定義、函式如何被應用以及遞迴的形式系統。它由數學家阿隆佐·邱奇在20世紀30年代首次發表。lambda演算作為一種廣泛用途的計算模型，可以清晰地定義什麼是一個可計算函式，而任何可計算函式都能以這種形式表達和求值，它能模擬單一磁帶图灵机的計算過程；儘管如此，lambda演算強調的是變換規則的運用，而非實現它們的具體機器。

lambda演算可比擬是最根本的編程語言，它包括了一條變換規則（變數替換）和一條將函式抽象化定義的方式。因此普遍公認是一種更接近軟體而非硬體的方式。對函數式編程語言造成很大影響，比如Lisp、ML语言和Haskell语言。在1936年邱奇利用λ演算給出了對於判定性問題（Entscheidungsproblem）的否定：關於兩個lambda運算式是否等價的命題，無法由一個「通用的演算法」判斷，這是不可判定效能夠證明的頭一個問題，甚至還在停机问题之先。

lambda演算包括了建構lambda項，和對lambda項執行歸約的操作。在最簡單的lambda演算中，只使用以下的規則來建構lambda項：

| 語法 | 名稱 | 描述 |
| --- | --- | --- |
| x | 變量 | 用字元或字串來表示參數或者數學上的值或者表示邏輯上的值 |
| (λx.M) | 抽象化 | 一個完整的函數定義（M是一個 lambda 項），在表達式中的 x 都會綁定為變量 x。 |
| (M N) | 應用 | 將函數M作用於參數N。 M 和 N 是 lambda 項。 |

產生了諸如：(λx.λy.(λz.(λx.zx)(λy.zy))(x y))的表達式。如果表達式是明確而沒有歧義的，則括號可以省略。對於某些應用，其中可能包括了邏輯和數學的常量以及相關操作。

本文討论的是邱奇的"无类型lambda演算"，此后，已经研究出来了一些有类型lambda演算。

解释与应用
-----

λ演算是图灵完备的，也就是说，这是一个可以用于模拟任何图灵机的通用模型。 λ也被用在**λ表达式**和**λ项**中，用来表示将一个变量绑定在一个函数上。

λ演算可以是**有类型**或者**无类型**的，在有类型λ演算中（上文所述是无类型的），函数只能在参数类型和输入类型符合时被应用。有类型λ演算比无类型λ演算要弱——后者是这个条目的主要部分——因为有类型的λ运算能表达的比无类型λ演算少；与此同时，前者使得更多定理能被证明。例如，在简单类型λ演算中，运算总是能够停止，然而无类型λ演算中这是不一定的（因为停机问题）。目前有许多种有类型λ演算的一个原因是它们被期望能做到更多（做到某些以前的有类型λ演算做不到的）的同时又希望能用以证明更多定理。

λ演算在数学、哲学、语言学和计算机科学中都有许多应用。它在程式語言理論中占有重要地位，函数式编程实现了λ演算支持。λ演算在范畴论中也是一个研究热点。

历史
--

作为对数学基础研究的一部分，数学家阿隆佐·邱奇在20世纪30年代提出了λ演算。 但最初的λ演算系统被证明是逻辑上不自洽的——在1935年斯蒂芬·科尔·克莱尼和J. B. Rosser举出了Kleene-Rosser悖论（英语：）。

随后，在1936年邱奇把那个版本的关于计算的部分抽出独立发表—现在这被称为无类型λ演算。 在1940年，他创立了一个计算能力更弱但是逻辑上自洽的系统，这被称为简单类型λ演算。

直到1960年，λ演算与编程语言的关系被确立了；在这之前它只是一个范式。由于理查德·蒙塔古和其他语言学家将λ演算应用于自然语言语法的研究，λ演算已经开始在语言学和计算机科学学界拥有一席之地。

至于为何邱奇选择λ作为符号，连他本人的解释也互相矛盾：最初是在1964年的一封信中，他明确解释称这是来源于《数学原理》一书中的类抽象符号（脱字符），为了方便阅读，他首先将其换成逻辑与符号（{\displaystyle \land }）作为区分，然后又改成形状类似的λ。他在1984年又重申了这一点，但再后来他又表示选择λ纯粹是偶然。

非形式化的直覺描述
---------

在λ演算中，每个表达式都代表一个函数，这个函数有一个参数，并且會返回一个值。不论是参数和返回值，也都是一个单参的函数。可以这么说，λ演算中只有一种"类型"，那就是这种单参函数。函数是通过λ表达式匿名地定义的，这个表达式说明了此函数将对其参数进行什么操作。

例如，"加2"函数f(x)= x + 2可以用lambda演算表示为λx.x + 2（或者λy.y + 2，参数的取名无关紧要），而f(3)的值可以写作(λx.x + 2) 3。函数的应用（application）是左结合的：f x y =(f x) y。

考虑这么一个函数：它把一个函数作为参数，这个函数将被作用在3上：λf.f 3。如果把这个（用函数作参数的）函数作用于我们先前的"加2"函数上：(λf.f 3)(λx.x+2)，则明显地，下述三个表达式：

(λf.f 3)(λx.x+2) 与 (λx.x + 2) 3 与 3 + 2
是等价的。有两个参数的函数可以通过lambda演算这樣表达：一个单一参数的函数，它的返回值又是一个单一参数的函数（参见柯里化）。例如，函数f(x, y) = x - y可以写作λx.λy.x - y。下述三个表达式：

(λx.λy.x - y) 7 2 与 (λy.7 - y) 2 与 7 - 2
也是等价的。然而这种lambda表达式之间的等价性，无法找到某个通用的函数来判定。

并非所有的lambda表达式都能被歸约至上述那样的确定值，考虑

(λx.x x)(λx.x x)
或

(λx.x x x)(λx.x x x)
然后试图把第一个函数作用在它的参数上。(λx.x x)被称为ω 组合子，((λx.x x)(λx.x x))被称为Ω，而((λx.x x x) (λx.x x x))被称为Ω2，以此类推。若仅形式化函数作用的概念而不允许lambda表达式，就得到了组合子逻辑。

### 動機

在數學和計算機科學中，「可計算的」函式是基礎觀念。對於所謂的可計算性，λ-演算提供了一個簡單明確的語義，使計算的性質可以被形式化研究。λ-演算結合了兩種簡化方式，使得這個語義變得簡單。第一種簡化是不給予函式一個確定名稱，而"匿名"地對待它們。例如，兩數的平方和函式

{\displaystyle \operatorname {square\\_sum} (x,y)=x^{2}+y^{2}}
可以用匿名的形式重新寫為：

{\displaystyle (x,y)\mapsto x^{2}+y^{2}}（理解成一包含x和y的數組被映射到{\textstyle x^{2}+y^{2}}）
同樣地，

{\displaystyle \operatorname {id} (x)=x}
可以用匿名的形式重新寫為：

{\displaystyle x\mapsto x}（即輸入是直接對應到它本身。）
第二個簡化是λ演算只使用單一個參數輸入的函數。如果普通函數需要兩個參數，例如{\textstyle \operatorname {square\\_sum} }函數，可轉成接受單一參數，傳給另一個函數中介，而中介函數也只接受一個參數，最後輸出結果。例如，

{\displaystyle (x,y)\mapsto x^{2}+y^{2}}
可以重新寫成：

{\displaystyle x\mapsto (y\mapsto x^{2}+y^{2})}
這是稱為柯里化的方法，將多參數的函數轉換成為多個中介函數的複合鏈，每個中介函數都只接受一個參數。
將{\textstyle \operatorname {square\\_sum} }函數應用於參數(5,2)，直接產生結果

{\textstyle ((x,y)\mapsto x^{2}+y^{2})(5,2)}
{\textstyle =5^{2}+2^{2}}
{\textstyle =29},
而對於柯里化轉換版的評估，需要再多一步：

{\textstyle {\Bigl (}{\bigl (}x\mapsto (y\mapsto x^{2}+y^{2}){\bigr )}(5){\Bigr )}(2)}
{\textstyle =(y\mapsto 5^{2}+y^{2})(2)} //在內層表達式中{\displaystyle x}的定義為{\displaystyle 5}，這就像β-歸約一樣。
{\textstyle =5^{2}+2^{2}} //{\displaystyle y}的定義為{\displaystyle 2}，再次如同β-歸約。
{\textstyle =29}
得出相同結果。

### lambda演算

lambda演算是由特定形式語法所組成的一種語言，一組轉換規則可操作其中的lambda項。這些轉換規則被看作是一個等式理論或者一個操作定義。如上節所述，lambda演算中的所有函數都是匿名的，它們沒有名稱，它們只接受一個輸入變量，柯里化用於實現有多個輸入變量的函數。

#### lambda項

lambda演算的語法將一些表達式定義為有效的lambda演算式，而某一些表達式無效，就像C編程語言中有些字串有效，有些則不是。有效的lambda演算式稱為"lambda項"。

以下三個規則給出了語法上有效的lambda項，如何建構的歸納定義：

* 變量{\displaystyle x}本身就是一個有效的lambda項
* 如果{\displaystyle t}是一個lambda項，而{\displaystyle x}是一個變量，則{\displaystyle (\lambda x.t)} 是一個lambda項（稱為**lambda抽象**）；
* 如果{\displaystyle t}和{\displaystyle s}是lambda項，那麼{\displaystyle (ts)}是一個lambda項（稱為**應用**）。

其它的都不是lambda項。因此，lambda項若且唯若可重複應用這三個規則取得時，才是有效的。一些括號根據某些規則可以省略。例如，最外面的括號通常不會寫入。

"lambda抽象"是指一個匿名函數的定義，它將單一輸入的{\displaystyle \lambda x.t}替換成{\displaystyle t}的表達式，所以產生了一個匿名函數，它採用{\displaystyle x}的值並返回{\displaystyle t}。例如，{\displaystyle \lambda x.x^{2}+2}是表示使用函數{\displaystyle f(x)=x^{2}+2}作為{\displaystyle t}項的一個lambda抽象。lambda抽象只是先"設置"了函數定義，還沒使用它。這個抽象在{\displaystyle t}項中綁定了變量{\displaystyle x}。一個**應用**{\displaystyle ts}表示將函數{\displaystyle t}應用在輸入{\displaystyle s}，亦即對輸入{\displaystyle s}使用函數{\displaystyle t}產生{\displaystyle t(s)}。

lambda演算中並沒有變量聲明的概念。如{\displaystyle \lambda x.x+y}（即{\displaystyle f(x)=x+y}）的定義中，lambda演算將{\displaystyle y}當作尚未定義的變量。lambda抽象{\displaystyle \lambda x.x+y}在語法上是有效的，並表示將其輸入添加到未知{\displaystyle y}的函數。

可用圓括弧對來消除歧義。例如，{\displaystyle \lambda x.((\lambda x.x)x)}和{\displaystyle (\lambda x.(\lambda x.x))x}表示不同的項（儘管它們剛好化簡到相同值）。這裡第一個例子定義了一個包含子函數的抽象，並將子函數應用於x（先應用後傳回）的結果；而第二個例子定義了一個傳回任何輸入的函數，然後在應用過程中傳回對輸入為x的應用（返回函數然後應用）。

#### 操作函數的函數

在lambda演算中，函數被認為是**頭等物件**，因此函數可以當作輸入，或作為其它函數的輸出返回。

例如，{\displaystyle \lambda x.x}表示映射到本身的函數，{\displaystyle x\mapsto x}和{\displaystyle (\lambda x.x)y}表示將這個函數應用於{\displaystyle y}。此外，{\displaystyle (\lambda x.y)}則表示無論輸入為何，始終返回{\displaystyle y}值的**常數函數**{\displaystyle x\mapsto y}。lambda演算中的函數應用是左結合的，因此{\displaystyle stx}表示{\displaystyle (st)x}。

有幾個"等價"和"化簡"的概念，允許將各個lambda項"縮減"為"相同"的lambda項。

#### {\displaystyle \alpha }-等價

對於lambda項，等價的基本形式定義，是{\displaystyle \alpha }-等價。它捕捉了直覺概念，在lambda抽象中一個綁定變量的特別選擇（通常）並不重要。
比如，{\displaystyle \lambda x.x}和{\displaystyle \lambda y.y}是{\displaystyle \alpha }-等價的lambda項，它們都表示相同的函數（自映射函數）；但如{\displaystyle x}和{\displaystyle y}項則不是{\displaystyle \alpha }-等價的，因為它們並非以lambda抽象方式綁定的。
在許多演示中，通常會確定{\displaystyle \alpha }-等價的lambda項。

為了能夠定義{\displaystyle \beta }-歸約，需要以下定義：

#### 自由變量

所謂的**自由變量**是那些在lambda抽象不受到綁定的變量。表達式中的一組自由變量定義歸納如下：

* {\displaystyle x}的自由變量就只是{\displaystyle x}
* {\displaystyle \lambda x.t}的自由變量集合，是在{\displaystyle t}中移除了{\displaystyle x}的自由變量集合。
* {\displaystyle ts}的自由變量是{\displaystyle t}的一組自由變量，與{\displaystyle s}的一組自由變量，這兩項變量的並集。

例如，代表映射自身的{\displaystyle \lambda x.x}，其中的lambda項沒有自由變量，但是在函數{\displaystyle \lambda x.yx}中的lambda項，有一個自由變量{\displaystyle y}。

#### 避免捕獲的替換記法

假設{\displaystyle t}，{\displaystyle s}和{\displaystyle r}是lambda項，而{\displaystyle x}和{\displaystyle y}是變量。如果寫成{\displaystyle t[x:=r]}是一種*避免被捕獲*的記法方式，表示在{\displaystyle t}這個lambda項中，以{\displaystyle r}來替換{\displaystyle x}變量的值。這定義為：

* {\displaystyle x[x:=r]=r}；
* {\displaystyle y[x:=r]=y}，如果{\displaystyle x\neq y}；
* {\displaystyle (ts)[x:=r]=(t[x:=r])(s[x:=r])}；
* {\displaystyle (\lambda x.t)[x:=r]=\lambda x.t}；
* 如果{\displaystyle x\neq y}而且{\displaystyle y}不在lambda項{\displaystyle r}的自由變量中，則{\displaystyle (\lambda y.t)[x:=r]=\lambda y.(t[x:=r])}。對於lambda項{\displaystyle r}，變量{\displaystyle y}被稱為是"新鮮"的。

例如，{\displaystyle (\lambda x.x)[y:=y]=\lambda x.(x[y:=y])=\lambda x.x}
和{\displaystyle ((\lambda x.y)x)[x:=y]=((\lambda x.y)[x:=y])(x[x:=y])=(\lambda x.y)y}。

新鮮度條件（要求{\displaystyle y}不在lambda項{\displaystyle r}中的自由變量中）對於確保替換不會改變函數的意義很重要。例如，忽視新鮮度條件的替代：{\displaystyle (\lambda x.y)[y:=x]=\lambda x.(y[y:=x])=\lambda x.x}。此替換會將原本意義為常量函數的{\displaystyle \lambda x.y}，轉換成意義為映射自身函數的{\displaystyle \lambda x.x}。

一般來說，在無法滿足新鮮度條件的情況，可利用{\displaystyle \alpha }-重新命名使用一個合適的新變量來補救，切換回正確的替換概念；比如在{\displaystyle (\lambda x.y)[y:=x]}中，使用一個新變量{\displaystyle z}重新命名這個lambda抽象，獲取{\displaystyle (\lambda z.y)[y:=x]=\lambda z.(y[y:=x])=\lambda z.x}，則替換就能保留原本函數的義涵。

#### {\displaystyle \beta }-歸約

β-歸約規定了形式如{\displaystyle (\lambda x.t)s}的應用，可以化簡成{\displaystyle t[x:=s]}項。符號記法{\displaystyle (\lambda x.t)s\to t[x:=s]}用於表示{\displaystyle (\lambda x.t)s} 經過β-歸約轉換為{\displaystyle t[x:=s]}。例如，對於每個{\displaystyle s}，可轉換為{\displaystyle (\lambda x.x)s\to x[x:=s]=s}。這表明{\displaystyle \lambda x.x}實際上的應用是映射自身函數。同樣地，{\displaystyle (\lambda x.y)s\to y[x:=s]=y}，表明了{\displaystyle \lambda x.y}是一個常量函數。

lambda演算可視為函數式編程語言的理想化版本，如Haskell或ML語言。在這種觀點下，β-歸約對應於一組計算步驟。
這個步驟重複應用β-轉換，一直到沒有東西能再被化簡。在無型別lambda演算中，如本文所述，這個歸約過程可能無法終止，
比如{\displaystyle \Omega =(\lambda x.xx)(\lambda x.xx)}，是個特殊的lambda項。這裡
{\displaystyle (\lambda x.xx)(\lambda x.xx)\to (xx)[x:=\lambda x.xx]=(x[x:=\lambda x.xx])(x[x:=\lambda x.xx])=(\lambda x.xx)(\lambda x.xx)}
也就是說，該lambda項在一次β-歸約中化簡到本身，因此歸約過程將永遠不會終止。

無型別lambda演算的另一方面是它並不區分不同種類的資料。例如，需要編寫只針對數字操作的功能。然而，在無型別的lambda演算中，沒有辦法避免函數被應用於真值、字串或其它非數字物件。

形式化定义
-----

形式化地，我们从一个标识符（identifier）的可数无穷集合开始，比如{a, b, c, ... x, y, z, x1, x2, ...}，则所有的lambda表达式可以通过下述以BNF范式表达的上下文无关文法描述：

1. <表达式> ::= <标识符>
2. <表达式> ::= (λ<标识符>.<表达式>)
3. <表达式> ::= (<表达式> <表达式>)

头两条规则用来生成函数，而第三条描述了函数是如何作用在参数上的。通常，lambda抽象（规则2）和函数作用（规则3）中的括弧在不会产生歧义的情况下可以省略。如下假定保证了不会产生歧义：（1）函数的作用是左结合的，和（2）lambda操作符被绑定到它后面的整个表达式。例如，表达式 (λx.x x)(λy.y) 可以简写成λ(x.x x) λy.y 。

类似λx.(x y)这样的lambda表达式并未定义一个函数，因为变量y的出现是自由的，即它并没有被绑定到表达式中的任何一个λ上。一个lambda表达式的自由变量的集合是通过下述规则（基于lambda表达式的结构归纳地）定义的：

1. 在表达式V中，V是变量，则这个表达式里自由变量的集合只有V。
2. 在表达式λV .E中（V是变量，E是另一个表达式），自由变量的集合是E中自由变量的集合减去变量V。因而，E中那些V被称为绑定在λ上。
3. 在表达式 (E E')中，自由变量的集合是E和E'中自由变量集合的并集。

例，对于表达式λx.x（我们将第一个x视作变量，第二个x视作表达式），其中表达式x中，由1，它的自由变量集合是x，又由2，表达式λx.x的自由变量的集合是表达式x的自由变量集合减去变量x。所以对于表达式λx.x，它的自由变量集合是空。  

例，对于表达式λx.x x由形式化描述的第3点，我们把它看作((λx.x)(x))，(λx.x)和(x)分别为表达式，由上一例知道(λx.x)的自由变量集合为空，表达式(x)的变量集合为变量x，所以对于λx.x x，它的自由变量集合为x与空的并，即x。

在lambda表达式的集合上定义了一个等价关系(在此用==标注)，"两个表达式其实表示的是同一个函数"这样的直觉性判断即由此表述，这种等价关系是通过所谓的"alpha-变换规则"和"beta-归约规则"。

歸約
--

歸約的操作包括：

| 操作 | 名稱 | 描述 |
| --- | --- | --- |
| (λx.M[x]) → (λy.M[y]) | α-轉換 | 重新命名表達式中的綁定（形式）變量。用於避免名稱衝突。 |
| ((λx.M) E) → (M[x:=E]) | β-歸約 | 在抽象化的函數定義體中，以參數表達式代替綁定變量。 |

### α-变换

Alpha-变换规则表达的是，被绑定变量的名称是不重要的。比如说λx.x和λy.y是同一个函数。尽管如此，这条规则并非像它看起来这么简单，关于被绑定的变量能否由另一个替换有一系列的限制。

Alpha-变换规则陈述的是，若V与W均为变量，E是一个lambda表达式，同时E[V:=W]是指把表达式E中的所有的V的自由出现都替换为W，那么在W不是
E中的一个自由出现，且如果W替换了V，W不会被E中的λ绑定的情况下，有

λV.E == λW.E[V:=W]
这条规则告诉我们，例如λx.(λx.x) x这样的表达式和λy.(λx.x) y是一样的。

### β-归约

Beta-归约规则表达的是函数作用的概念。它陈述了若所有的E'的自由出现在E [V:=E']中仍然是自由的情况下，有

((λV.E) E') == E [V:=E']
成立。

==关系被定义为满足上述两条规则的最小等价关系（即在这个等价关系中减去任何一个映射，它将不再是一个等价关系）。

对上述等价关系的一个更具操作性的定义可以这样获得：只允许从左至右来应用规则。不允许任何beta归约的lambda表达式被称为**Beta范式**。并非所有的lambda表达式都存在与之等价的范式，若存在，则对于相同的形式参数命名而言是唯一的。此外，有一个算法用户计算范式，不断地把最左边的形式参数替换为实际参数，直到无法再作任何可能的规约为止。这个算法当且仅当lambda表达式存在一个范式时才会停止。Church-Rosser定理说明了，当且仅当两个表达式等价时，它们会在形式参数换名后得到同一个范式。

### η-变换

前两条规则之后，还可以加入第三条规则，eta-变换，来形成一个新的等价关系。Eta-变换表达的是外延性的概念，在这里外延性指的是，对于任一給定的参数，当且仅当两个函数得到的结果都一致，則它们將被視同為一个函数。Eta-变换可以令 {\displaystyle \lambda x.fx} 和 {\displaystyle f} 相互转换，只要 {\displaystyle x} 不是 {\displaystyle f} 中的自由變量。下面说明了为何这条规则和外延性是等价的：

若 {\displaystyle f} 与 {\displaystyle g} 外延地等价，即，{\displaystyle fa==ga} 对所有的 {\displaystyle \lambda } 表达式 {\displaystyle a}成立，则当取 {\displaystyle a} 为在 {\displaystyle f} 中不是自由出现的变量 {\displaystyle x}时，我们有{\displaystyle f(x)==g(x)}，因此 {\displaystyle \lambda x.fx==\lambda x.gx}，由eta-变换f == g。所以只要eta-变换是有效的，会得到外延性也是有效的。

相反地，若外延性是有效的，则由beta-归约，对所有的y有(λx .f x) y == f y，可得λx .f x == f，即eta-变换也是有效的。

資料類型的編碼
-------

基本的lambda演算法可用於建構布林值，算術，資料結構和遞歸的模型，如以下各小節所述。

### lambda演算中的算術

在lambda演算中有许多方式都可以定义自然数，但最常见的还是邱奇数，下面是它们的定义：

```
0 = λf.λx.x
1 = λf.λx.f x
2 = λf.λx.f (f x)
3 = λf.λx.f (f (f x))
```

以此类推。直观地说，lambda演算中的数字n就是一个把函数f作为参数并以f的n次幂为返回值的函数。换句话说，邱奇整数是一个高阶函数 -- 以单一参数函数f为参数，返回另一个单一参数的函数。

(注意在邱奇原来的lambda演算中，lambda表达式的形式参数在函数体中至少出现一次，这使得我们无法像上面那样定义0)在邱奇整数定义的基础上，我们可以定义一个后继函数，它以n为参数，返回n + 1：

```
SUCC = λn.λf.λx.f(n f x)
```

加法是这样定义的：

```
PLUS = λm.λn.λf.λx.m f (n f x)
```

PLUS可以被看作以两个自然数为参数的函数，它返回的也是一个自然数。你可以试试验证

```
PLUS 2 3 
```

与5是否等价。乘法可以这样定义：

```
MULT = λm.λn.m (PLUS n) 0,
```

即m乘以n等于在零的基础上m次加n。另一种方式是

```
MULT = λm.λn.λf.m (n f)
```

正整数n的前驱元（predecessesor）PRED n = n - 1要复杂一些：

```
PRED = λn.λf.λx.n (λg.λh.h (g f)) (λu.x) (λu.u)
```

或者

```
PRED = λn.n(λg.λk.(g 1) (λu.PLUS(g k) 1) k) (λl.0) 0
```

注意`(g 1)(λu.PLUS(g k) 1) k`表示的是，当`g(1)`是零时，表达式的值是`k`，否则是`g(k)+ 1`。

### 逻辑与谓词

习惯上，下述两个定义（称为邱奇布尔值）被用作TRUE和FALSE这样的布尔值：

TRUE := λx.λy.x
FALSE := λx.λy.y
(注意FALSE等价于前面定义邱奇数零)
接着，通过这两个λ-项，我们可以定义一些逻辑运算：

AND := λp q.p q FALSE
OR := λp q.p TRUE q
NOT := λp.p FALSE TRUE
IFTHENELSE := λp x y.p x y
我们现在可以计算一些逻辑函数，比如：

AND TRUE FALSE
≡(λp q.p q FALSE) TRUE FALSE →β TRUE FALSE FALSE
≡(λx y.x) FALSE FALSE →β FALSE
我们见到AND TRUE FALSE等价于FALSE。

"谓词"是指返回布尔值的函数。最基本的一个谓词是ISZERO，当且仅当其参数为零时返回真，否则返回假：

ISZERO := λn.n (λx.FALSE) TRUE
运用谓词与上述TRUE和FALSE的定义，使得"if-then-else"这类语句很容易用lambda演算写出。

### 有序对

有序对（2-元组）数据类型可以用TRUE、FALSE和IF来定义。

CONS := λx y.λp.IF p x y
CAR := λx.x TRUE
CDR := λx.x FALSE
链表数据类型可以定义为，要么是为空列表保留的值（e.g.FALSE），要么是CONS一个元素和一个更小的列表。

附加的編程技術
-------

lambda演算出現在相當大量的編程習慣用法中，其中許多編程語言最初以lambda演算作為語義基礎，在此背景下開發的；有效地利用lambda演算作為基底。因為幾個編程語言部份含括了lambda演算（或者非常相似的東西），所以這些技術也可以在實際的編程中見到，但有可能被認為是模糊或外來的。

### 命名常數

在lambda演算中，函式庫將採用預先定義好的函數集合，其中lambda項僅僅是特定的常量。純粹的lambda演算法並不具有命名常數的概念，因為所有的原子λ項都是變量；但是在程序主體中，我們可將一個變量當成常量的名稱，利用lambda抽象把這個變量綁定，並將該lambda抽象應用於預期的定義，來模擬命名常量的作法。因此在*N*（"主程序"的另一個lambda項）中，要以*f*來表示*M*（一些明確的lambda項），則寫成如下：

(λ*f*.*N*) *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 n·f(n-1)。
在lambda演算中，你不能定义包含自身的函数。要避免这样，你可以开始于定义一个函数，这里叫g，它接受一个函数f作为参数并返回接受n作为参数的另一个函数：

g := λf n.(if n = 0 then 1 else n·f(n-1))。
函数g返回要么常量1，要么函数f对n-1的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.(λx.g(x x))(λx.g(x x))
在lambda演算中，Y g是g的不动点，因为它展开为g(Y g)。现在，要完成我们对阶乘函数的递归调用，我们可以简单的调用 g(Y g)n，这裡的n是我们要计算它的阶乘的数。

比如假定n = 5，它展开为：

(λn.(if n = 0 then 1 else n·((Y g)(n-1)))) 5
 if 5 = 0 then 1 else 5·(g(Y g，5-1))
5·(g(Y g)4)
5·(λn.(if n = 0 then 1 else n·((Y g)(n-1))) 4)
5·(if 4 = 0 then 1 else 4·(g(Y g，4-1)))
5·(4·(g(Y g)3))
5·(4·(λn.(if n = 0 then 1 else n·((Y g)(n-1))) 3))
5·(4·(if 3 = 0 then 1 else 3·(g(Y g，3-1))))
5·(4·(3·(g(Y g)2)))
 ...
等等，递归的求值算法的结构。所有递归定义的函数都可以看作某个其他适当的函数的不动点，因此，使用Y所有递归定义的函数都可以表达为lambda表达式。特别是，我们现在可以明晰的递归定义自然数的减法、乘法和比较谓词。

### 標準化的組合子名稱

某一些lambda項有普遍接受的名稱：

 **I** := λ*x*.*x*
 **K** := λ*x*.λ*y*.*x*
 **S** := λ*x*.λ*y*.λ*z*.*x* *z* (*y* *z*) 
 **B** := λ*x*.λ*y*.λ*z*.*x* (*y* *z*) 
 **C** := λ*x*.λ*y*.λ*z*.*x* *z* *y*
 **W** := λ*x*.λ*y*.*x* *y* *y*
 **U** := λ*x*.λ*y*.*y* (*x* *x* *y*) 
 **ω** := λ*x*.*x* *x* 
 **Ω** := **ω** **ω** 
 **Y** := λ*g*.(λ*x*.*g* (*x* *x*)) (λ*x*.*g* (*x* *x*))
其中有幾個在"消除lambda抽象"中有直接的應用，將lambda項變為組合演算的術語。

### 消除lambda抽象

如果*N*是一個沒有λ-抽象的lambda項，但可能包含了命名常量（組合子），則存在一個lambda項*T*(*x*,*N*)，這相同於一個缺少λ-抽象（除了作為命名常量的一部份，如果這些被認為是非原子的）的λ*x*.*N*；也可以被視為匿名變量，就如同*T*(*x*,*N*)從*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*(*x*,*N*)*P*可藉由使初始的組合子**I**，**K**或**S**獲取參數*P*而化簡，
就像(λ*x*.*N*) *P*經過β-歸約一樣。**I**返回那個參數。**K**則將參數拋棄，就像(λ*x*.*N*)，如果*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")、 C++11等。

### 化簡策略

### 關於複雜度的註釋

### 並行與並發

参见
--

* 邱奇-图灵论题
* 递归函数
* 可计算函数
* 柯里化

参考文献
----

1. ↑  Turing, A. M.. The Journal of Symbolic Logic. December 1937, **2** (4): 153–163. JSTOR 2268280. doi:10.2307/2268280.
2. ↑  Coquand, Thierry, "Type Theory" （页面存档备份，存于）, *The Stanford Encyclopedia of Philosophy* (Summer 2013 Edition), Edward N. Zalta (ed.).
3. ↑  Moortgat, Michael.. Foris Publications. 1988. ISBN 9789067653879.
4. ↑  Bunt, Harry; Muskens, Reinhard (编), Springer, 2008, ISBN 9781402059575
5. ↑  Mitchell, John C. Cambridge University Press: 57, 2003, ISBN 9780521780988
6. ↑  Pierce, Benjamin C. . : 53.
7. ↑  Church, A.. Annals of Mathematics. Series 2. 1932, **33** (2): 346–366. JSTOR 1968337. doi:10.2307/1968337.
8. ↑  For a full history, see Cardone and Hindley's "History of Lambda-calculus and Combinatory Logic" (2006).
9. ↑  Kleene, S. C.; Rosser, J. B.. The Annals of Mathematics. July 1935, **36** (3): 630. doi:10.2307/1968646.
10. ↑  Church, Alonzo.. The Journal of Symbolic Logic. December 1942, **7** (4): 170–171. JSTOR 2268117. doi:10.2307/2268117.
11. ↑  Church, A.. American Journal of Mathematics. 1936, **58** (2): 345–363. JSTOR 2371045. doi:10.2307/2371045.
12. ↑  Church, A.. Journal of Symbolic Logic. 1940, **5** (2): 56–68. JSTOR 2266170. doi:10.2307/2266170.
13. ↑  Partee, B. B. H.; ter Meulen, A.; Wall, R. E.. Springer. 1990  [29 Dec 2016].
14. ↑  Alama, Jesse "The Lambda Calculus" （页面存档备份，存于）, *The Stanford Encyclopedia of Philosophy* (Summer 2013 Edition), Edward N. Zalta (ed.).
15. ↑  Cardon, Felice; Hindley, J. Roger.. 2006.

外部連結
----

* L.Allison, Some executable λ-calculus examples （页面存档备份，存于）
* Georg P.Loczewski, The Lambda Calculus and A++ （页面存档备份，存于）
* To Dissect a Mockingbird: A Graphical Notation for the Lambda Calculus with Animated Reduction
* 人物介紹
* 神奇的λ演算 （页面存档备份，存于）
* (译) The Y combinator (Slight Return)
* Λ運算︰淵源介紹 （页面存档备份，存于）


|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
处理器技术 |
| --- |
|  |
| 模型 | 

|  |  |
| --- | --- |
| 顺序模型 | 
* 图灵机
	+ 通用
	+ 波斯特-图灵机
	+ 量子
* 传动带机器（英语：）
* 堆疊結構機器
* 有限状态机
	+ 具数据通路（英语：）
	+ 分层（英语：）
	+ 队列（英语：）
* 寄存器机
	+ 计数器
	+ 指针（英语：）
	+ 隨機存取機
	+ 隨機存取儲存程式機

 |
|  |
| 函数式模型 | 
* 递归函数
* Λ演算
* 组合子逻辑
* 細胞自動機

 |

 |
|  |
| 架構 | 
* 微架構
* 冯·诺伊曼结构
* 哈佛架構
	+ 修正哈佛架構（英语：）
* 資料流架構（英语：）
* 传输触发（英语：）
* 元胞（英语：）
* 字节序
* 异构（英语：）
* Fabric（英语：）
* 多元處理
* 認知計算
* 神经形态（英语：）

|  |  |
| --- | --- |
| 内存访问 | 
* 非均匀访存模型(NUMA)
* 均匀访存模型(UMA)
* 载入/存储（英语：）
* 寄存器/存储器（英语：）

 |
|  |
| 缓存层级（英语：） | 
* 缓存层级（英语：）

 |
|  |
| 記憶體階層 | 
* 虚拟内存
* 第二级存储器

 |

 |
|  |
| 指令集架構 | 

|  |  |
| --- | --- |
| 类型 | 
* 复杂指令集(CISC)
* 精简指令集(RISC)
* 专用指令集处理器
* 显式数据图像并行（英语：）(EDGE)
	+ TRIPS（英语：）
* 超長指令集(VLIW)
* 顯式並行指令運算(EPIC)
* 最小指令集（英语：）(MISC)
* 單一指令集(OISC)
* 無指令集（英语：）(NISC)
	+ 零指令集(ZISC)
* 比較（英语：）

 |
|  |
| 指令集 | 
* x86
* ARM
* MIPS
* LoongArch
* PowerPC
* SPARC
* IA-64
* Unicore（英语：）
* MicroBlaze（英语：）
* RISC-V
* LMC（英语：）
* 其他（英语：）

 |

 |
|  |
| 执行 | 

|  |  |
| --- | --- |
|  | 
* 流水线停顿
* 操作数转发（英语：）
* 经典 RISC 流水线（英语：）

 |
|  |
| 危障 | 
* 数据依赖
* 數據危障
* 結構危障
* 控制危障
* 伪共享

 |
|  |
| 乱序执行 | 
* 托马苏洛算法
	+ 保留站
	+ 重排序缓冲区
* 寄存器重命名

 |
|  |
| 推测执行 | 
* 分支預測
	+ 存储相关性预测（英语：）

 |

 |
|  |
|  | 

|  |  |
| --- | --- |
| 并行层次 | 
* 位级并行
	+ 位序列（英语：）
	+ 字
* 指令级并行
* + 标量
	+ 純量
	+ 超純量
* 任務并行
	+ 线程
	+
* 数据并行
	+ 向量
* 記憶體
* 分布式

 |
|  |
| 執行緒 | 
* 多執行緒
* 同时多线程
	+ 超執行緒
* 超執行緒
* 超級線程（英语：）
* 预测多线程（英语：）
* 抢占式
* 协作式

 |
|  |
| 費林分類法 | 
* 單指令流單數據流(SISD)
* 單指令流多數據流(SIMD)
	+ 寄存器内（英语：）
* 单指令多线程（英语：）(SIMT)
* 多指令流單數據流(MISD)
* 多指令流多數據流(MIMD)
	+ 单程序多数据（英语：）

 |

 |
|  |
| 電腦性能 | 
* 晶體管數量
* 每周期指令(IPC)
	+ 每指令周期(CPI)
* 每秒指令(IPS)
* 每秒浮點運算次數(FLOPS)
* 每秒事务处理量 (TPS)
* 效能功耗比(PPW)

 |
|  |
| 類別 | 
* 中央处理器(CPU)
* 圖形處理器(GPU)
	+ 图形处理器通用计算(GPGPU)
* 向量处理器
* 桶状（英语：）
* 串流處理
* 輔助處理器
* 特殊應用積體電路(ASIC)
* 现场可编程逻辑门阵列(FPGA)
* 複雜可程式化邏輯裝置(CPLD)
* 多晶片模組(MCM)
* 封裝體系(SiP)

|  |  |
| --- | --- |
| 按应用 | 
* 微处理器
* 单片机(MCU)
* 移动处理器（英语：）
* 笔记本电脑处理器（英语：）
* 超低电压（英语：）
* 专用指令集处理器(ASIP)

 |
|  |
| 片上系统 | 
* 片上系统(SoC)
* 多处理器片上系统（英语：）(MPSoC)
* 可编程片上系统(PSoC)
* 片上网络（英语：）(NoC)

 |
|  |
| 硬件加速 | 
* 人工智能加速器
* 视觉处理单元(VPU)
* 物理處理器(PPU)
* 數位訊號處理器(DSP)
* 张量处理器(TPU)
* 安全加密協處理器
* 网络处理器
* 基頻處理器

 |

 |
|  |
| 字长 | 
* 
* 4位元
* 8位元
* 12位元
* 
* 16位元
* 24位元（英语：）
* 32位元
* 48位元（英语：）
* 64位元
* 128位元
* 
* 位元分割（英语：）
* 其他
	+

 |
|  |
| 核心数量 | 
* 单核（英语：）
* 多核
* 众核（英语：）
* 异构

 |
|  |
| 組件 | 
* 核心
* 缓存
	+ CPU缓存
	+ 置換機制
	+ 一致性
* 总线
* 
* 定時器訊號
* 先進先出演算法(FIFO)

|  |  |
| --- | --- |
| 功能单元 | 
* 算術邏輯單元(ALU)
* 地址生成单元(AGU)
* 浮點運算器(FPU)
* 內存管理單元(MMU)
	+ 载入-存储单元（英语：）
	+ 轉譯後備緩衝區(TLB)
* 内存控制器(IMC)

 |
|  |
| 邏輯閘 | 
* 组合逻辑电路
* 时序逻辑电路
* Glue（英语：）
* 邏輯閘
	+ 量子閘
	+ 逻辑门阵列（英语：）

 |
|  |
| 寄存器 | 
* 寄存器
* 状态寄存器（英语：）
* 栈寄存器（英语：）
* 寄存器堆
* 記憶體缓冲区
* 程式計數器

 |
|  |
| 总线 | 
* 位址匯流排
* 控制匯流排
* 后端总线

 |
|  |
| 控制单元 | 
* 指令单元（英语：）
* 緩衝器
* 写入缓冲区（英语：）
* 微程序ROM
* 计数器

 |
|  |
| 数据通路 | 
* 数据选择器
* 数据分配器
* 加法器
* 乘法器
	+ CPU倍频器
* 译码器
	+ 地址解码器（英语：）
	+ 加和寻址解码器（英语：）
* 桶式移位器

 |
|  |
| 電路 | 
* 集成电路
	+ 3D
	+ 混合訊號
	+ 電源管理
* 布尔（英语：）
* 数字
* 模拟
* 量子
* 开关

 |

 |
|  |
| 电源管理 | 
* 电源管理单元（英语：）(PMU)
* 高级电源管理
* 高级配置与电源接口(ACPI)
* 
* 动态电压调节
* 时钟门控
* 效能功耗比(PPW)
* 空闲竞争（英语：）

 |
|  |
| 相关内容 | 
* 通用CPU历史（英语：）
* 微处理器年代表（英语：）
* 处理器设计
* 数字电路
* 硬件安全模块
* 半导体制造
* Tick-Tock
* 推測執行漏洞集合

 |

 |