fbpx
维基百科

λ演算

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

lambda演算可比擬是最根本的編程語言,它包括了一條變換規則(變數替換)和一條將函式抽象化定義的方式。因此普遍公認是一種更接近軟體而非硬體的方式。對函數式編程語言造成很大影響,比如LispML语言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演算

解释与应用

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

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

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

历史

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

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

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

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

非形式化的直覺描述

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

例如,“加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表达式,就得到了组合子逻辑

動機

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

 

可以用匿名的形式重新寫為:

 (理解成一包含xy的數組被映射到 

同樣地,

 

可以用匿名的形式重新寫為:

 (即輸入是直接對應到它本身。)

第二個簡化是λ演算只使用單一個參數輸入的函數。如果普通函數需要兩個參數,例如 函數,可轉成接受單一參數,傳給另一個函數中介,而中介函數也只接受一個參數,最後輸出結果。例如,

 

可以重新寫成:

 

這是稱為柯里化的方法,將多參數的函數轉換成為多個中介函數的複合鏈,每個中介函數都只接受一個參數。 將 函數應用於參數(5,2),直接產生結果

 
 
 ,

而對於柯里化轉換版的評估,需要再多一步:

 
  //在內層表達式中 的定義為 ,這就像β-歸約一樣。
  // 的定義為 ,再次如同β-歸約。
 

得出相同結果。

lambda演算

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

lambda項

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

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

  • 變量 本身就是一個有效的lambda項
  • 如果 是一個lambda項,而 是一個變量,則  是一個lambda項(稱為lambda抽象);
  • 如果  是lambda項,那麼 是一個lambda項(稱為應用)。

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

“lambda抽象”是指一個匿名函數的定義,它將單一輸入的 替換成 的表達式,所以產生了一個匿名函數,它採用 的值並返回 。例如, 是表示使用函數 作為 項的一個lambda抽象。lambda抽象只是先“設置”了函數定義,還沒使用它。這個抽象在 項中綁定了變量 。一個應用 表示將函數 應用在輸入 ,亦即對輸入 使用函數 產生 

lambda演算中並沒有變量聲明的概念。如 (即 )的定義中,lambda演算將 當作尚未定義的變量。lambda抽象 在語法上是有效的,並表示將其輸入添加到未知 的函數。

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

操作函數的函數

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

例如, 表示映射到本身的函數,  表示將這個函數應用於 。此外, 則表示無論輸入為何,始終返回 值的常數函數 。lambda演算中的函數應用是左結合的,因此 表示 

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

 -等價

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

為了能夠定義 -歸約,需要以下定義:

自由變量

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

  •  的自由變量就只是 
  •  的自由變量集合,是在 中移除了 的自由變量集合。
  •  的自由變量是 的一組自由變量,與 的一組自由變量,這兩項變量的並集。

例如,代表映射自身的 ,其中的lambda項沒有自由變量,但是在函數 中的lambda項,有一個自由變量 

避免捕獲的替換記法

假設   是lambda項,而  是變量。如果寫成 是一種避免被捕獲的記法方式,表示在 這個lambda項中,以 來替換 變量的值。這定義為:

  •  
  •  ,如果 
  •  
  •  
  • 如果 而且 不在lambda項 的自由變量中,則 。對於lambda項 ,變量 被稱為是“新鮮”的。

例如,  

新鮮度條件(要求 不在lambda項 中的自由變量中)對於確保替換不會改變函數的意義很重要。例如,忽視新鮮度條件的替代: 。此替換會將原本意義為常量函數的 ,轉換成意義為映射自身函數的 

一般來說,在無法滿足新鮮度條件的情況,可利用 -重新命名使用一個合適的新變量來補救,切換回正確的替換概念;比如在 中,使用一個新變量 重新命名這個lambda抽象,獲取 ,則替換就能保留原本函數的義涵。

 -歸約

β-歸約規定了形式如 的應用,可以化簡成 項。符號記法 用於表示  經過β-歸約轉換為 。例如,對於每個 ,可轉換為 。這表明 實際上的應用是映射自身函數。同樣地, ,表明了 是一個常量函數。

lambda演算可視為函數式編程語言的理想化版本,如HaskellML語言。在這種觀點下,β-歸約對應於一組計算步驟。 這個步驟重複應用β-轉換,一直到沒有東西能再被化簡。在無型別lambda演算中,如本文所述,這個歸約過程可能無法終止, 比如 ,是個特殊的lambda項。這裡   也就是說,該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-变换可以令    相互转换,只要   不是   中的自由變量。下面说明了为何这条规则和外延性是等价的:

   外延地等价,即,  对所有的   表达式  成立,则当取   为在   中不是自由出现的变量  时,我们有 ,因此  ,由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

逻辑与谓词

习惯上,下述两个定义(称为邱奇布尔值)被用作TRUEFALSE这样的布尔值:

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

运用谓词与上述TRUEFALSE的定义,使得"if-then-else"这类语句很容易用lambda演算写出。

有序对

有序对(2-元组)数据类型可以用TRUEFALSEIF来定义。

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,要么函数fn-1的n次应用。使用ISZERO谓词,和上面描述的布尔和代数定义,函数g可以用lambda演算来定义。

但是,g自身仍然不是递归的;为了使用g来建立递归函数,作为参数传递给gf函数必须有特殊的性质。也就是说,作为参数传递的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 gg的不动点,因为它展开为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 := λxy.x
S := λxyz.x z (y z)
B := λxyz.x (y z)
C := λxyz.x z y
W := λxy.x y y
U := λxy.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可藉由使初始的組合子IKS獲取參數P而化簡, 就像x.N) P經過β-歸約一樣。I返回那個參數。K則將參數拋棄,就像x.N),如果xN中不是以自由變量出現。S將參數傳遞給應用程序的兩個子句,然後將第一個結果應用到第二個的結果之上。

組合子BC類似於S,但把參數傳遞給應用的一個子項(B傳給“參數”子項,而C傳給“函數”子項),如果子項中沒有出現x,則保存後續的K。與BC相比,S組合子實際上混合了兩個功能: 重新排列參數,並複製一個參數,以便它可以在兩個地方使用。W組合子只做後者,產生了SKI组合子演算的B,C,K,W系統。

可计算函数和lambda演算

自然数的函数F: NN可计算函数当且仅当存在着一个lambda表达式f,使得对于N中的每对x, y都有F(x) = y当且仅当f x == y,这裡的xy分别是对应于x和y的邱奇数。这是定义可计算性的多种方式之一;关于其他方式和它们的等价者的讨论请参见邱奇-图灵论题

lambda演算與編程語言

匿名函數

比如计算平方的函数 square 在 Lisp 中可以表示为如下的 lambda 表达式

(lambda (x) (* x x)) 

符号 lambda 创建一个匿名函数,给定参数列表 (x) ,以及一个作为函数体的表达式 (* x x)。 匿名函数有时称为 lambda 表达式。

很多命令式语言都有函数指针或者类似的机制。但是函数指针并不是类型中的一等公民,函数是一等公民当且仅当函数可以在运行时创建。 下面一些语言支持函数的运行时创建: SmalltalkJavaScriptKotlinScalaPython3C# ("delegates")、 C++11等。

化簡策略

關於複雜度的註釋

並行與並發

参见

参考文献

  1. ^ Turing, A. M. Computability and λ-Definability. 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. Categorial Investigations: Logical and Linguistic Aspects of the Lambek Calculus. Foris Publications. 1988. ISBN 9789067653879. 
  4. ^ Bunt, Harry; Muskens, Reinhard (编), Computing Meaning, Springer, 2008, ISBN 9781402059575 
  5. ^ Mitchell, John C., Concepts in Programming Languages, Cambridge University Press: 57, 2003, ISBN 9780521780988 
  6. ^ Pierce, Benjamin C. Basic Category Theory for Computer Scientists. : 53. 
  7. ^ Church, A. A set of postulates for the foundation of logic. 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 Inconsistency of Certain Formal Logics. The Annals of Mathematics. July 1935, 36 (3): 630. doi:10.2307/1968646. 
  10. ^ Church, Alonzo. Review of Haskell B. Curry, The Inconsistency of Certain Formal Logics. The Journal of Symbolic Logic. December 1942, 7 (4): 170–171. JSTOR 2268117. doi:10.2307/2268117. 
  11. ^ Church, A. An unsolvable problem of elementary number theory. American Journal of Mathematics. 1936, 58 (2): 345–363. JSTOR 2371045. doi:10.2307/2371045. 
  12. ^ Church, A. A Formulation of the Simple Theory of Types. 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. Mathematical Methods in Linguistics. 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. History of Lambda-calculus and Combinatory Logic. 2006. 

外部連結


λ演算, 此條目包含過多行話或專業術語, 可能需要簡化或提出進一步解釋, 請在討論頁中發表對於本議題的看法, 並移除或解釋本條目中的行話, 英語, lambda, calculus, calculus, 是一套從數學邏輯中發展, 以變數綁定和替換的規則, 來研究函式如何抽象化定義, 函式如何被應用以及遞迴的形式系統, 它由數學家阿隆佐, 邱奇在20世紀30年代首次發表, lambda演算作為一種廣泛用途的計算模型, 可以清晰地定義什麼是一個可計算函式, 而任何可計算函式都能以這種形式表達和求值, 它能模擬單一磁帶图. 此條目包含過多行話或專業術語 可能需要簡化或提出進一步解釋 請在討論頁中發表對於本議題的看法 並移除或解釋本條目中的行話 l演算 英語 lambda calculus l calculus 是一套從數學邏輯中發展 以變數綁定和替換的規則 來研究函式如何抽象化定義 函式如何被應用以及遞迴的形式系統 它由數學家阿隆佐 邱奇在20世紀30年代首次發表 lambda演算作為一種廣泛用途的計算模型 可以清晰地定義什麼是一個可計算函式 而任何可計算函式都能以這種形式表達和求值 它能模擬單一磁帶图灵机的計算過程 儘管如此 lambda演算強調的是變換規則的運用 而非實現它們的具體機器 lambda演算可比擬是最根本的編程語言 它包括了一條變換規則 變數替換 和一條將函式抽象化定義的方式 因此普遍公認是一種更接近軟體而非硬體的方式 對函數式編程語言造成很大影響 比如Lisp ML语言和Haskell语言 在1936年邱奇利用l演算給出了對於判定性問題 Entscheidungsproblem 的否定 關於兩個lambda運算式是否等價的命題 無法由一個 通用的演算法 判斷 這是不可判定效能夠證明的頭一個問題 甚至還在停机问题之先 lambda演算包括了建構lambda項 和對lambda項執行歸約的操作 在最簡單的lambda演算中 只使用以下的規則來建構lambda項 語法 名稱 描述x 變量 用字元或字串來表示參數或者數學上的值或者表示邏輯上的值 lx M 抽象化 一個完整的函數定義 M是一個 lambda 項 在表達式中的 x 都會綁定為變量 x M N 應用 將函數M作用於參數N M 和 N 是 lambda 項 產生了諸如 lx ly lz lx zx ly zy x y 的表達式 如果表達式是明確而沒有歧義的 則括號可以省略 對於某些應用 其中可能包括了邏輯和數學的常量以及相關操作 本文討论的是邱奇的 无类型lambda演算 此后 已经研究出来了一些有类型lambda演算 目录 1 解释与应用 2 历史 3 非形式化的直覺描述 3 1 動機 3 2 lambda演算 3 2 1 lambda項 3 2 2 操作函數的函數 3 2 3 UNIQ postMath 00000051 QINU 等價 3 2 4 自由變量 3 2 5 避免捕獲的替換記法 3 2 6 UNIQ postMath 00000085 QINU 歸約 4 形式化定义 5 歸約 5 1 a 变换 5 2 b 归约 5 3 h 变换 6 資料類型的編碼 6 1 lambda演算中的算術 6 2 逻辑与谓词 6 3 有序对 7 附加的編程技術 7 1 命名常數 7 2 递归與不動點 7 3 標準化的組合子名稱 7 4 消除lambda抽象 8 可计算函数和lambda演算 9 lambda演算與編程語言 9 1 匿名函數 9 2 化簡策略 9 3 關於複雜度的註釋 9 4 並行與並發 10 参见 11 参考文献 12 外部連結解释与应用 编辑l演算是图灵完备的 也就是说 这是一个可以用于模拟任何图灵机的通用模型 1 l也被用在l表达式和l项中 用来表示将一个变量绑定在一个函数上 l演算可以是有类型或者无类型的 在有类型l演算中 上文所述是无类型的 函数只能在参数类型和输入类型符合时被应用 有类型l演算比无类型l演算要弱 后者是这个条目的主要部分 因为有类型的l运算能表达的比无类型l演算少 与此同时 前者使得更多定理能被证明 例如 在简单类型l演算中 运算总是能够停止 然而无类型l演算中这是不一定的 因为停机问题 目前有许多种有类型l演算的一个原因是它们被期望能做到更多 做到某些以前的有类型l演算做不到的 的同时又希望能用以证明更多定理 l演算在数学 哲学 2 语言学 3 4 和计算机科学 5 中都有许多应用 它在程式語言理論中占有重要地位 函数式编程实现了l演算支持 l演算在范畴论中也是一个研究热点 6 历史 编辑作为对数学基础研究的一部分 数学家阿隆佐 邱奇在20世纪30年代提出了l演算 7 8 但最初的l演算系统被证明是逻辑上不自洽的 在1935年斯蒂芬 科尔 克莱尼和J B Rosser举出了Kleene Rosser悖论 英语 Kleene Rosser paradox 9 10 随后 在1936年邱奇把那个版本的关于计算的部分抽出独立发表 现在这被称为无类型l演算 11 在1940年 他创立了一个计算能力更弱但是逻辑上自洽的系统 这被称为简单类型l演算 12 直到1960年 l演算与编程语言的关系被确立了 在这之前它只是一个范式 由于理查德 蒙塔古和其他语言学家将l演算应用于自然语言语法的研究 l演算已经开始在语言学 13 和计算机科学学界拥有一席之地 14 至于为何邱奇选择l作为符号 连他本人的解释也互相矛盾 最初是在1964年的一封信中 他明确解释称这是来源于 数学原理 一书中的类抽象符号 脱字符 为了方便阅读 他首先将其换成逻辑与符号作为区分 然后又改成形状类似的l 他在1984年又重申了这一点 但再后来他又表示选择l纯粹是偶然 15 非形式化的直覺描述 编辑在l演算中 每个表达式都代表一个函数 这个函数有一个参数 并且會返回一个值 不论是参数和返回值 也都是一个单参的函数 可以这么说 l演算中只有一种 类型 那就是这种单参函数 函数是通过l表达式匿名地定义的 这个表达式说明了此函数将对其参数进行什么操作 例如 加2 函数f x x 2可以用lambda演算表示为lx x 2 或者ly y 2 参数的取名无关紧要 而f 3 的值可以写作 lx x 2 3 函数的应用 application 是左结合的 f x y f x y 考虑这么一个函数 它把一个函数作为参数 这个函数将被作用在3上 lf f 3 如果把这个 用函数作参数的 函数作用于我们先前的 加2 函数上 lf f 3 lx x 2 则明显地 下述三个表达式 lf f 3 lx x 2 与 lx x 2 3 与 3 2是等价的 有两个参数的函数可以通过lambda演算这樣表达 一个单一参数的函数 它的返回值又是一个单一参数的函数 参见柯里化 例如 函数f x y x y可以写作lx ly x y 下述三个表达式 lx ly x y 7 2 与 ly 7 y 2 与 7 2也是等价的 然而这种lambda表达式之间的等价性 无法找到某个通用的函数来判定 并非所有的lambda表达式都能被歸约至上述那样的确定值 考虑 lx x x lx x x 或 lx x x x lx x x x 然后试图把第一个函数作用在它的参数上 lx x x 被称为w 组合子 lx x x lx x x 被称为W 而 lx x x x lx x x x 被称为W2 以此类推 若仅形式化函数作用的概念而不允许lambda表达式 就得到了组合子逻辑 動機 编辑 在數學和計算機科學中 可計算的 函式是基礎觀念 對於所謂的可計算性 l 演算提供了一個簡單明確的語義 使計算的性質可以被形式化研究 l 演算結合了兩種簡化方式 使得這個語義變得簡單 第一種簡化是不給予函式一個確定名稱 而 匿名 地對待它們 例如 兩數的平方和函式 s q u a r e s u m x y x 2 y 2 displaystyle operatorname square sum x y x 2 y 2 可以用匿名的形式重新寫為 x y x 2 y 2 displaystyle x y mapsto x 2 y 2 理解成一包含x 和y 的數組被映射到x 2 y 2 textstyle x 2 y 2 同樣地 id x x displaystyle operatorname id x x 可以用匿名的形式重新寫為 x x displaystyle x mapsto x 即輸入是直接對應到它本身 第二個簡化是l演算只使用單一個參數輸入的函數 如果普通函數需要兩個參數 例如s q u a r e s u m textstyle operatorname square sum 函數 可轉成接受單一參數 傳給另一個函數中介 而中介函數也只接受一個參數 最後輸出結果 例如 x y x 2 y 2 displaystyle x y mapsto x 2 y 2 可以重新寫成 x y x 2 y 2 displaystyle x mapsto y mapsto x 2 y 2 這是稱為柯里化的方法 將多參數的函數轉換成為多個中介函數的複合鏈 每個中介函數都只接受一個參數 將s q u a r e s u m textstyle operatorname square sum 函數應用於參數 5 2 直接產生結果 x y x 2 y 2 5 2 textstyle x y mapsto x 2 y 2 5 2 5 2 2 2 textstyle 5 2 2 2 29 textstyle 29 而對於柯里化轉換版的評估 需要再多一步 x y x 2 y 2 5 2 textstyle Bigl bigl x mapsto y mapsto x 2 y 2 bigr 5 Bigr 2 y 5 2 y 2 2 textstyle y mapsto 5 2 y 2 2 在內層表達式中x displaystyle x 的定義為5 displaystyle 5 這就像b 歸約一樣 5 2 2 2 textstyle 5 2 2 2 y displaystyle y 的定義為2 displaystyle 2 再次如同b 歸約 29 textstyle 29 得出相同結果 lambda演算 编辑 lambda演算是由特定形式語法所組成的一種語言 一組轉換規則可操作其中的lambda項 這些轉換規則被看作是一個等式理論或者一個操作定義 如上節所述 lambda演算中的所有函數都是匿名的 它們沒有名稱 它們只接受一個輸入變量 柯里化用於實現有多個輸入變量的函數 lambda項 编辑 lambda演算的語法將一些表達式定義為有效的lambda演算式 而某一些表達式無效 就像C編程語言中有些字串有效 有些則不是 有效的lambda演算式稱為 lambda項 以下三個規則給出了語法上有效的lambda項 如何建構的歸納定義 變量x displaystyle x 本身就是一個有效的lambda項 如果t displaystyle t 是一個lambda項 而x displaystyle x 是一個變量 則 l x t displaystyle lambda x t 是一個lambda項 稱為lambda抽象 如果t displaystyle t 和s displaystyle s 是lambda項 那麼 t s displaystyle ts 是一個lambda項 稱為應用 其它的都不是lambda項 因此 lambda項若且唯若可重複應用這三個規則取得時 才是有效的 一些括號根據某些規則可以省略 例如 最外面的括號通常不會寫入 lambda抽象 是指一個匿名函數的定義 它將單一輸入的l x t displaystyle lambda x t 替換成t displaystyle t 的表達式 所以產生了一個匿名函數 它採用x displaystyle x 的值並返回t displaystyle t 例如 l x x 2 2 displaystyle lambda x x 2 2 是表示使用函數f x x 2 2 displaystyle f x x 2 2 作為t displaystyle t 項的一個lambda抽象 lambda抽象只是先 設置 了函數定義 還沒使用它 這個抽象在t displaystyle t 項中綁定了變量x displaystyle x 一個應用t s displaystyle ts 表示將函數t displaystyle t 應用在輸入s displaystyle s 亦即對輸入s displaystyle s 使用函數t displaystyle t 產生t s displaystyle t s lambda演算中並沒有變量聲明的概念 如l x x y displaystyle lambda x x y 即f x x y displaystyle f x x y 的定義中 lambda演算將y displaystyle y 當作尚未定義的變量 lambda抽象l x x y displaystyle lambda x x y 在語法上是有效的 並表示將其輸入添加到未知y displaystyle y 的函數 可用圓括弧對來消除歧義 例如 l x l x x x displaystyle lambda x lambda x x x 和 l x l x x x displaystyle lambda x lambda x x x 表示不同的項 儘管它們剛好化簡到相同值 這裡第一個例子定義了一個包含子函數的抽象 並將子函數應用於x 先應用後傳回 的結果 而第二個例子定義了一個傳回任何輸入的函數 然後在應用過程中傳回對輸入為x的應用 返回函數然後應用 操作函數的函數 编辑 在lambda演算中 函數被認為是頭等物件 因此函數可以當作輸入 或作為其它函數的輸出返回 例如 l x x displaystyle lambda x x 表示映射到本身的函數 x x displaystyle x mapsto x 和 l x x y displaystyle lambda x x y 表示將這個函數應用於y displaystyle y 此外 l x y displaystyle lambda x y 則表示無論輸入為何 始終返回y displaystyle y 值的常數函數x y displaystyle x mapsto y lambda演算中的函數應用是左結合的 因此s t x displaystyle stx 表示 s t x displaystyle st x 有幾個 等價 和 化簡 的概念 允許將各個lambda項 縮減 為 相同 的lambda項 a displaystyle alpha 等價 编辑 對於lambda項 等價的基本形式定義 是a displaystyle alpha 等價 它捕捉了直覺概念 在lambda抽象中一個綁定變量的特別選擇 通常 並不重要 比如 l x x displaystyle lambda x x 和l y y displaystyle lambda y y 是a displaystyle alpha 等價的lambda項 它們都表示相同的函數 自映射函數 但如x displaystyle x 和y displaystyle y 項則不是a displaystyle alpha 等價的 因為它們並非以lambda抽象方式綁定的 在許多演示中 通常會確定a displaystyle alpha 等價的lambda項 為了能夠定義b displaystyle beta 歸約 需要以下定義 自由變量 编辑 所謂的自由變量是那些在lambda抽象不受到綁定的變量 表達式中的一組自由變量定義歸納如下 x displaystyle x 的自由變量就只是x displaystyle x l x t displaystyle lambda x t 的自由變量集合 是在t displaystyle t 中移除了x displaystyle x 的自由變量集合 t s displaystyle ts 的自由變量是t displaystyle t 的一組自由變量 與s displaystyle s 的一組自由變量 這兩項變量的並集 例如 代表映射自身的l x x displaystyle lambda x x 其中的lambda項沒有自由變量 但是在函數l x y x displaystyle lambda x yx 中的lambda項 有一個自由變量y displaystyle y 避免捕獲的替換記法 编辑 假設t displaystyle t s displaystyle s 和r displaystyle r 是lambda項 而x displaystyle x 和y displaystyle y 是變量 如果寫成t x r displaystyle t x r 是一種避免被捕獲的記法方式 表示在t displaystyle t 這個lambda項中 以r displaystyle r 來替換x displaystyle x 變量的值 這定義為 x x r r displaystyle x x r r y x r y displaystyle y x r y 如果x y displaystyle x neq y t s x r t x r s x r displaystyle ts x r t x r s x r l x t x r l x t displaystyle lambda x t x r lambda x t 如果x y displaystyle x neq y 而且y displaystyle y 不在lambda項r displaystyle r 的自由變量中 則 l y t x r l y t x r displaystyle lambda y t x r lambda y t x r 對於lambda項r displaystyle r 變量y displaystyle y 被稱為是 新鮮 的 例如 l x x y y l x x y y l x x displaystyle lambda x x y y lambda x x y y lambda x x 和 l x y x x y l x y x y x x y l x y y displaystyle lambda x y x x y lambda x y x y x x y lambda x y y 新鮮度條件 要求y displaystyle y 不在lambda項r displaystyle r 中的自由變量中 對於確保替換不會改變函數的意義很重要 例如 忽視新鮮度條件的替代 l x y y x l x y y x l x x displaystyle lambda x y y x lambda x y y x lambda x x 此替換會將原本意義為常量函數的l x y displaystyle lambda x y 轉換成意義為映射自身函數的l x x displaystyle lambda x x 一般來說 在無法滿足新鮮度條件的情況 可利用a displaystyle alpha 重新命名使用一個合適的新變量來補救 切換回正確的替換概念 比如在 l x y y x displaystyle lambda x y y x 中 使用一個新變量z displaystyle z 重新命名這個lambda抽象 獲取 l z y y x l z y y x l z x displaystyle lambda z y y x lambda z y y x lambda z x 則替換就能保留原本函數的義涵 b displaystyle beta 歸約 编辑 b 歸約規定了形式如 l x t s displaystyle lambda x t s 的應用 可以化簡成t x s displaystyle t x s 項 符號記法 l x t s t x s displaystyle lambda x t s to t x s 用於表示 l x t s displaystyle lambda x t s 經過b 歸約轉換為t x s displaystyle t x s 例如 對於每個s displaystyle s 可轉換為 l x x s x x s s displaystyle lambda x x s to x x s s 這表明l x x displaystyle lambda x x 實際上的應用是映射自身函數 同樣地 l x y s y x s y displaystyle lambda x y s to y x s y 表明了l x y displaystyle lambda x y 是一個常量函數 lambda演算可視為函數式編程語言的理想化版本 如Haskell或ML語言 在這種觀點下 b 歸約對應於一組計算步驟 這個步驟重複應用b 轉換 一直到沒有東西能再被化簡 在無型別lambda演算中 如本文所述 這個歸約過程可能無法終止 比如W l x x x l x x x displaystyle Omega lambda x xx lambda x xx 是個特殊的lambda項 這裡 l x x x l x x x x x x l x x x x x l x x x x x l x x x l x x x l x x x 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項在一次b 歸約中化簡到本身 因此歸約過程將永遠不會終止 無型別lambda演算的另一方面是它並不區分不同種類的資料 例如 需要編寫只針對數字操作的功能 然而 在無型別的lambda演算中 沒有辦法避免函數被應用於真值 字串或其它非數字物件 形式化定义 编辑形式化地 我们从一个标识符 identifier 的可数无穷集合开始 比如 a b c x y z x1 x2 则所有的lambda表达式可以通过下述以BNF范式表达的上下文无关文法描述 lt 表达式 gt lt 标识符 gt lt 表达式 gt l lt 标识符 gt lt 表达式 gt lt 表达式 gt lt 表达式 gt lt 表达式 gt 头两条规则用来生成函数 而第三条描述了函数是如何作用在参数上的 通常 lambda抽象 规则2 和函数作用 规则3 中的括弧在不会产生歧义的情况下可以省略 如下假定保证了不会产生歧义 1 函数的作用是左结合的 和 2 lambda操作符被绑定到它后面的整个表达式 例如 表达式 lx x x ly y 可以简写成l x x x ly y 类似lx x y 这样的lambda表达式并未定义一个函数 因为变量y的出现是自由的 即它并没有被绑定到表达式中的任何一个l上 一个lambda表达式的自由变量的集合是通过下述规则 基于lambda表达式的结构归纳地 定义的 在表达式V中 V是变量 则这个表达式里自由变量的集合只有V 在表达式lV E中 V是变量 E是另一个表达式 自由变量的集合是E中自由变量的集合减去变量V 因而 E中那些V被称为绑定在l上 在表达式 E E 中 自由变量的集合是E和E 中自由变量集合的并集 例 对于表达式lx x 我们将第一个x视作变量 第二个x视作表达式 其中表达式x中 由1 它的自由变量集合是x 又由2 表达式lx x的自由变量的集合是表达式x的自由变量集合减去变量x 所以对于表达式lx x 它的自由变量集合是空 例 对于表达式lx x x由形式化描述的第3点 我们把它看作 lx x x lx x 和 x 分别为表达式 由上一例知道 lx x 的自由变量集合为空 表达式 x 的变量集合为变量x 所以对于lx x x 它的自由变量集合为x与空的并 即x 在lambda表达式的集合上定义了一个等价关系 在此用 标注 两个表达式其实表示的是同一个函数 这样的直觉性判断即由此表述 这种等价关系是通过所谓的 alpha 变换规则 和 beta 归约规则 歸約 编辑歸約的操作包括 操作 名稱 描述 lx M x ly M y a 轉換 重新命名表達式中的綁定 形式 變量 用於避免名稱衝突 lx M E M x E b 歸約 在抽象化的函數定義體中 以參數表達式代替綁定變量 a 变换 编辑 Alpha 变换规则表达的是 被绑定变量的名称是不重要的 比如说lx x和ly y是同一个函数 尽管如此 这条规则并非像它看起来这么简单 关于被绑定的变量能否由另一个替换有一系列的限制 Alpha 变换规则陈述的是 若V与W均为变量 E是一个lambda表达式 同时E V W 是指把表达式E中的所有的V的自由出现都替换为W 那么在W不是 E中的一个自由出现 且如果W替换了V W不会被E中的l绑定的情况下 有 lV E lW E V W 这条规则告诉我们 例如lx lx x x这样的表达式和ly lx x y是一样的 b 归约 编辑 Beta 归约规则表达的是函数作用的概念 它陈述了若所有的E 的自由出现在E V E 中仍然是自由的情况下 有 lV E E E V E 成立 关系被定义为满足上述两条规则的最小等价关系 即在这个等价关系中减去任何一个映射 它将不再是一个等价关系 对上述等价关系的一个更具操作性的定义可以这样获得 只允许从左至右来应用规则 不允许任何beta归约的lambda表达式被称为Beta范式 并非所有的lambda表达式都存在与之等价的范式 若存在 则对于相同的形式参数命名而言是唯一的 此外 有一个算法用户计算范式 不断地把最左边的形式参数替换为实际参数 直到无法再作任何可能的规约为止 这个算法当且仅当lambda表达式存在一个范式时才会停止 Church Rosser定理说明了 当且仅当两个表达式等价时 它们会在形式参数换名后得到同一个范式 h 变换 编辑 前两条规则之后 还可以加入第三条规则 eta 变换 来形成一个新的等价关系 Eta 变换表达的是外延性的概念 在这里外延性指的是 对于任一給定的参数 当且仅当两个函数得到的结果都一致 則它们將被視同為一个函数 Eta 变换可以令 l x f x displaystyle lambda x fx 和 f displaystyle f 相互转换 只要 x displaystyle x 不是 f displaystyle f 中的自由變量 下面说明了为何这条规则和外延性是等价的 若 f displaystyle f 与 g displaystyle g 外延地等价 即 f a g a displaystyle fa ga 对所有的 l displaystyle lambda 表达式 a displaystyle a 成立 则当取 a displaystyle a 为在 f displaystyle f 中不是自由出现的变量 x displaystyle x 时 我们有f x g x displaystyle f x g x 因此 l x f x l x g x displaystyle lambda x fx lambda x gx 由eta 变换f g 所以只要eta 变换是有效的 会得到外延性也是有效的 相反地 若外延性是有效的 则由beta 归约 对所有的y有 lx f x y f y 可得lx f x f 即eta 变换也是有效的 資料類型的編碼 编辑基本的lambda演算法可用於建構布林值 算術 資料結構和遞歸的模型 如以下各小節所述 lambda演算中的算術 编辑 在lambda演算中有许多方式都可以定义自然数 但最常见的还是邱奇数 下面是它们的定义 0 lf lx x 1 lf lx f x 2 lf lx f f x 3 lf lx f f f x 以此类推 直观地说 lambda演算中的数字n就是一个把函数f作为参数并以f的n次幂为返回值的函数 换句话说 邱奇整数是一个高阶函数 以单一参数函数f为参数 返回另一个单一参数的函数 注意在邱奇原来的lambda演算中 lambda表达式的形式参数在函数体中至少出现一次 这使得我们无法像上面那样定义0 在邱奇整数定义的基础上 我们可以定义一个后继函数 它以n为参数 返回n 1 SUCC ln lf lx f n f x 加法是这样定义的 PLUS lm ln lf lx m f n f x PLUS可以被看作以两个自然数为参数的函数 它返回的也是一个自然数 你可以试试验证 PLUS 2 3 与5是否等价 乘法可以这样定义 MULT lm ln m PLUS n 0 即m乘以n等于在零的基础上m次加n 另一种方式是 MULT lm ln lf m n f 正整数n的前驱元 predecessesor PRED n n 1要复杂一些 PRED ln lf lx n lg lh h g f lu x lu u 或者 PRED ln n lg lk g 1 lu PLUS g k 1 k ll 0 0 注意 g 1 lu PLUS g k 1 k表示的是 当g 1 是零时 表达式的值是k 否则是g k 1 逻辑与谓词 编辑 习惯上 下述两个定义 称为邱奇布尔值 被用作TRUE和FALSE这样的布尔值 TRUE lx ly x FALSE lx ly y 注意FALSE等价于前面定义邱奇数零 dd 接着 通过这两个l 项 我们可以定义一些逻辑运算 AND lp q p q FALSE OR lp q p TRUE q NOT lp p FALSE TRUE IFTHENELSE lp x y p x y我们现在可以计算一些逻辑函数 比如 AND TRUE FALSE lp q p q FALSE TRUE FALSE b TRUE FALSE FALSE lx y x FALSE FALSE b FALSE dd 我们见到AND TRUE FALSE等价于FALSE 谓词 是指返回布尔值的函数 最基本的一个谓词是ISZERO 当且仅当其参数为零时返回真 否则返回假 ISZERO ln n lx FALSE TRUE运用谓词与上述TRUE和FALSE的定义 使得 if then else 这类语句很容易用lambda演算写出 有序对 编辑 有序对 2 元组 数据类型可以用TRUE FALSE和IF来定义 CONS lx y lp IF p x y CAR lx x TRUE CDR lx x FALSE链表数据类型可以定义为 要么是为空列表保留的值 e g FALSE 要么是CONS一个元素和一个更小的列表 附加的編程技術 编辑lambda演算出現在相當大量的編程習慣用法中 其中許多編程語言最初以lambda演算作為語義基礎 在此背景下開發的 有效地利用lambda演算作為基底 因為幾個編程語言部份含括了lambda演算 或者非常相似的東西 所以這些技術也可以在實際的編程中見到 但有可能被認為是模糊或外來的 命名常數 编辑 在lambda演算中 函式庫將採用預先定義好的函數集合 其中lambda項僅僅是特定的常量 純粹的lambda演算法並不具有命名常數的概念 因為所有的原子l項都是變量 但是在程序主體中 我們可將一個變量當成常量的名稱 利用lambda抽象把這個變量綁定 並將該lambda抽象應用於預期的定義 來模擬命名常量的作法 因此在N 主程序 的另一個lambda項 中 要以f來表示M 一些明確的lambda項 則寫成如下 lf N M作者經常引入類似如let的语法糖 允許以更直觀的次序撰寫上述內容 let f MinN通過等號鏈接這個命名常數 即可將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 lf 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 lg lx g x x lx g x x 在lambda演算中 Y g是g的不动点 因为它展开为g Y g 现在 要完成我们对阶乘函数的递归调用 我们可以简单的调用g Y g n 这裡的n是我们要计算它的阶乘的数 比如假定n 5 它展开为 ln 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 ln 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 ln 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 lx x K lx ly x S lx ly lz x z y z B lx ly lz x y z C lx ly lz x z y W lx ly x y y U lx ly y x x y w lx x x W w w Y lg lx g x x lx g x x 其中有幾個在 消除lambda抽象 中有直接的應用 將lambda項變為組合演算的術語 消除lambda抽象 编辑 如果N是一個沒有l 抽象的lambda項 但可能包含了命名常量 組合子 則存在一個lambda項T x N 這相同於一個缺少l 抽象 除了作為命名常量的一部份 如果這些被認為是非原子的 的lx 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而化簡 就像 lx N P經過b 歸約一樣 I返回那個參數 K則將參數拋棄 就像 lx 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等 化簡策略 编辑 關於複雜度的註釋 编辑 並行與並發 编辑参见 编辑邱奇 图灵论题 递归函数 可计算函数 柯里化参考文献 编辑 Turing A M Computability and l Definability The Journal of Symbolic Logic December 1937 2 4 153 163 JSTOR 2268280 doi 10 2307 2268280 Coquand Thierry Type Theory 页面存档备份 存于互联网档案馆 The Stanford Encyclopedia of Philosophy Summer 2013 Edition Edward N Zalta ed Moortgat Michael Categorial Investigations Logical and Linguistic Aspects of the Lambek Calculus Foris Publications 1988 ISBN 9789067653879 Bunt Harry Muskens Reinhard 编 Computing Meaning Springer 2008 ISBN 9781402059575 Mitchell John C Concepts in Programming Languages Cambridge University Press 57 2003 ISBN 9780521780988 Pierce Benjamin C Basic Category Theory for Computer Scientists 53 Church A A set of postulates for the foundation of logic Annals of Mathematics Series 2 1932 33 2 346 366 JSTOR 1968337 doi 10 2307 1968337 For a full history see Cardone and Hindley s History of Lambda calculus and Combinatory Logic 2006 Kleene S C Rosser J B The Inconsistency of Certain Formal Logics The Annals of Mathematics July 1935 36 3 630 doi 10 2307 1968646 Church Alonzo Review of Haskell B Curry The Inconsistency of Certain Formal Logics The Journal of Symbolic Logic December 1942 7 4 170 171 JSTOR 2268117 doi 10 2307 2268117 Church A An unsolvable problem of elementary number theory American Journal of Mathematics 1936 58 2 345 363 JSTOR 2371045 doi 10 2307 2371045 Church A A Formulation of the Simple Theory of Types Journal of Symbolic Logic 1940 5 2 56 68 JSTOR 2266170 doi 10 2307 2266170 Partee B B H ter Meulen A Wall R E Mathematical Methods in Linguistics Springer 1990 29 Dec 2016 Alama Jesse The Lambda Calculus 页面存档备份 存于互联网档案馆 The Stanford Encyclopedia of Philosophy Summer 2013 Edition Edward N Zalta ed Cardon Felice Hindley J Roger History of Lambda calculus and Combinatory Logic 2006 外部連結 编辑L Allison Some executable l calculus examples 页面存档备份 存于互联网档案馆 Georg P Loczewski The Lambda Calculus and A 页面存档备份 存于互联网档案馆 To Dissect a Mockingbird A Graphical Notation for the Lambda Calculus with Animated Reduction 人物介紹 神奇的l演算 页面存档备份 存于互联网档案馆 译 The Y combinator Slight Return L運算 淵源介紹 页面存档备份 存于互联网档案馆 取自 https zh wikipedia org w index php title L演算 amp oldid 74762301, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。