λ演算
历史
最开始,邱奇试图创制一套完整的形式系统作为数学的基础,当他发现这个系统易受罗素悖论的影响时,就把lambda演算单独分离出来,用于研究可计算性,最终导致了他对判定性问题的否定回答。
非形式化的描述
在λ演算中,每个表达式都代表一个函数,这个函数有一个参数,并且返回一个值。不论是参数和返回值,也都是一个单参的函数。可以这么说,λ演算中,只有一种“类型”,那就是这种单参函数。
函数是通过λ表达式匿名地定义的,这个表达式说明了此函数将对其参数进行什么操作。例如,“加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),则明显地,下述三个表达式:
是等价的。有两个参数的函数可以通过lambda演算这么表达:一个单一参数的函数的返回值又是一个单一参数的函数(参见Currying)。例如,函数f(x, y) = x - y可以写作λx.λy.x - y。下述三个表达式:
也是等价的。然而这种lambda表达式之间的等价性无法找到一个通用的函数来判定。
并非所有的lambda表达式都可以规约至上述那样的确定值,考虑
或
然后试图把第一个函数作用在它的参数上。 (λx.x x)被称为ω组合子,((λx.x x)(λx.x x))被称为Ω,而((λx.x x x) (λx.x x x))被称为Ω2,以此类推。
若仅形式化函数作用的概念而不允许lambda表达式,就得到了组合子逻辑。
形式化定义
形式化地,我们从一个标识符(identifier)的可数无穷集合开始,比如{a, b, c, ..., x, y, z, x1, x2, ...},则所有的lambda表达式可以通过下述以BNF范式表达的上下文无关文法描述:
::=
::= (λ.)
::= ( )
头两条规则用来生成函数,而第三条描述了函数是如何作用在参数上的。通常,lambda抽象(规则2)和函数作用(规则3)中的括号在不会产生歧义的情况下可以省略。如下假定保证了不会产生歧义:(1)函数的作用是左结合的,和(2)lambda操作符被绑定到它后面的整个表达式。例如,表达式 (λx.x x)(λy.y) 可以简写成λ(x.x x) λy.y 。
类似λx.(x y)这样的lambda表达式并未定义一个函数,因为变量y的出现是自由的,即它并没有被绑定到表达式中的任何一个λ上。一个lambda表达式的自由变量的集合是通过下述规则(基于lambda表达式的结构归纳地)定义的:
在表达式V中,V是变量,则这个表达式里自由变量的集合只有V。
在表达式λV .E中(V是变量,E是另一个表达式),自由变量的集合是E中自由变量的集合减去变量V。因而,E中那些V被称为绑定在λ上。
在表达式 (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-归约规则”。
归约
α-变换
Alpha-变换规则表达的是,被绑定变量的名称是不重要的。比如说λx.x和λy.y是同一个函数。尽管如此,这条规则并非像它看起来这么简单,关于被绑定的变量能否由另一个替换有一系列的限制。
Alpha-变换规则陈述的是,若V与W均为变量,E是一个lambda表达式,同时E[V:=W]是指把表达式E中的所有的V的自由出现都替换为W,那么在W不是 E中的一个自由出现,且如果W替换了V,W不会被E中的λ绑定的情况下,有
这条规则告诉我们,例如λx.(λx.x) x这样的表达式和λy.(λx.x) y是一样的。
β-归约
Beta-归约规则表达的是函数作用的概念。它陈述了若所有的E"的自由出现在E [V:=E"]中仍然是自由的情况下,有
成立。
==关系被定义为满足上述两条规则的最小等价关系(即在这个等价关系中减去任何一个映射,它将不再是一个等价关系)。
对上述等价关系的一个更具操作性的定义可以这样获得:只允许从左至右来应用规则。不允许任何beta归约的lambda表达式被称为Beta范式。并非所有的lambda表达式都存在与之等价的范式,若存在,则对于相同的形式参数命名而言是唯一的。此外,有一个算法用户计算范式,不断地把最左边的形式参数替换为实际参数,直到无法再作任何可能的规约为止。这个算法当且仅当lambda表达式存在一个范式时才会停止。Church-Rosser定理说明了,当且仅当两个表达式等价时,它们会在形式参数换名后得到同一个范式。
η-变换
前两条规则之后,还可以加入第三条规则,eta-变换,来形成一个新的等价关系。Eta-变换表达的是外延性的概念,在这里外延性指的是,两个函数对于所有的参数得到的结果都一致,当且仅当它们是同一个函数。Eta-变换可以令λx .f x和f相互转换,只要x不是f中的自由出现。下面说明了为何这条规则和外延性是等价的:
若f与g外延地等价,即,f a == g a对所有的lambda表达式a成立,则当取a为在f中不是自由出现的变量x时,我们有f x == g x,因此λx .f x == λx .g x,由eta-变换f == g。所以只要eta-变换是有效的,会得到外延性也是有效的。
相反地,若外延性是有效的,则由beta-归约,对所有的y有(λx .f x) y == f y,可得λx .f x == f,即eta-变换也是有效的。
lambda演算中的算术
在lambda演算中有许多方式都可以定义自然数,但最常见的还是邱奇数,下面是它们的定义:
以此类推。直观地说,lambda演算中的数字n就是一个把函数f作为参数并以f的n次幂为返回值的函数。换句话说,邱奇整数是一个高阶函数-- 以单一参数函数f为参数,返回另一个单一参数的函数。
(注意在邱奇原来的lambda演算中,lambda表达式的形式参数在函数体中至少出现一次,这使得我们无法像上面那样定义0)在邱奇整数定义的基础上,我们可以定义一个后继函数,它以n为参数,返回n + 1:
加法是这样定义的:
PLUS可以被看作以两个自然数为参数的函数,它返回的也是一个自然数。你可以试试验证
与5是否等价。乘法可以这样定义:
即m乘以n等于在零的基础上m次加n。另一种方式是
正整数n的前驱元(predecessesor)PRED n = n - 1要复杂一些:
或者
注意(g 1)(λu.PLUS(g k) 1) k表示的是,当g(1)是零时,表达式的值是k,否则是g(k)+ 1。
逻辑与谓词
习惯上,下述两个定义(称为邱奇布尔值)被用作TRUE和FALSE这样的布尔值:
接着,通过这两个λ-项,我们可以定义一些逻辑运算:
我们现在可以计算一些逻辑函数,比如:
我们见到AND TRUE FALSE等价于FALSE。
“谓词”是指返回布尔值的函数。最基本的一个谓词是ISZERO,当且仅当其参数为零时返回真,否则返回假:
运用谓词与上述TRUE和FALSE的定义,使得"if-then-else"这类语句很容易用lambda演算写出。
有序对
有序对(2-元组)数据类型可以用TRUE、FALSE和IF来定义。
链表数据类型可以定义为,要么是为空列表保留的值(e.g.FALSE),要么是CONS一个元素和一个更小的列表。
递归
递归是使用函数自身的函数定义;在表面上,lambda演算不允许这样。但是这种印象是误解。考虑个例子,阶乘函数f(n)递归的定义为
在lambda演算中,你不能定义包含自身的函数。要避免这样,你可以开始于定义一个函数,这里叫g,它接受一个函数f作为参数并返回接受n作为参数的另一个函数:
函数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组合子:
在lambda演算中,Y g是g的不动点,因为它展开为g(Y g)。现在,要完成我们对阶乘函数的递归调用,我们可以简单的调用 g(Y g)n,这里的n是我们要计算它的阶乘的数。
比如假定n = 5,它展开为:
等等,递归的求值算法的结构。所有递归定义的函数都可以看作某个其他适当的函数的不动点,因此,使用Y所有递归定义的函数都可以表达为lambda表达式。特别是,我们现在可以明晰的递归定义自然数的减法、乘法和比较谓词。
可计算函数和lambda演算
自然数的函数F: N → N是可计算函数,当且仅当存在着一个lambda表达式f,使得对于N中的每对x, y都有F(x) = y当且仅当f x == y,这里的x和y分别是对应于x和y的邱奇数。这是定义可计算性的多种方式之一;关于其他方式和它们的等价者的讨论请参见邱奇-图灵论题。
参见
邱奇-图灵论题
递归函数
可计算函数
柯里化
免责声明:以上内容版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。感谢每一位辛勤著写的作者,感谢每一位的分享。
- 有价值
- 一般般
- 没价值