lambda演算


简单起见,全部采用f(2,3)而不是(f 2 3)的形式

BNF范式

<expr> ::= <identifier>

<expr> ::= lambda <identifier-list>. <expr>

<expr> ::= (<expr> <expr>)

lambda可以视作匿名函数,如
(lambda x y.x + y)
如何调用上述函数?
((lambda x y.x + y) 2 3)
可以通过语法糖的方式得到命名函数
let add = (lambda x y. x + y)
add(2,3)

阿尔法规约和贝塔规约

Alpha转换公理:例如,“lambda x y.x + y”转换为“lambda a b.a + b”。换句话说,函数的参数起什么名字没有关系,可以随意替换,只要函数体里面对参数的使用的地方也同时注意相应替换掉就是了。

Beta转换公理:例如,“(lambda x y. x + y) 2 3”转换为“2 + 3”。这个就更简单了,也就是说,当把一个lambda函数用到参数身上时,只需用实际的参数来替换掉其函数体中的相应变量即可。

Y-combinator

简单起见,考虑没有终止条件的递归求阶乘函数factorial
伪代码

factorial (n)
  return n * factorial(n - 1);

翻译成lambda,可以发现匿名函数中无法调用自己

lambda n.n * <???>(n - 1)

为了解决这个问题,考虑加一个参数,并采用语法糖

let factorial = lambda f n.n * f(f,n - 1)
factorial(factorial,5)                    

一个重要性质:函数即数据


现在引入不动点的概念

假设,我们已经构造出了一个完美的factorial,它可以以常规的方式递归自己(实际上lambda系统中无法定义出此函数)

let perfect_factorial = lambda n.n * perfect_factorial(n - 1)

此外,定义出F函数,一个伪递归

let F = lambda f n.n * f(n - 1)

我们可以先给出F的f参数(perfect_factorial),得到一个新的lambda函数

let new_F = lambda n.n * perfect_factorial(n - 1)

那么,可以发现,new_F 和 perfect_factorial 没有区别,二者等价,即

F(perfect_factorial) = perfect_factorial

那么对于P来说,perfect_factorial就是它的不动点
直观的说如果f(x) = x,x就是f的不动点


通过不动点的概念,我们可以推理出,对于任意的伪递归F

let F = lambda f n.n * f(n - 1)

必然存在一个完美的f,使得F(f) = f


假设存在一个神奇的Y-combinator,当它作用于伪递归F时,可以求出P对应的完美的函数f
即Y(F) = f,结合上文中的F(f) = f,我们可以得到

Y(F) = f = F(f) = F(Y(F))

Y(F) = F(Y(F))

如何求出这个神奇的Y?显然构造可得

let Y = lambda F.

let self_f = lambda self.F(self(self))

return  self_f(self_f)                      

我们将伪递归F带入演算:

let F = lambda f n.n * f(n - 1)

let self_f = lambda self.F(self(self))
           = lambda self.(lambda f n.n * f(n - 1))(self(self))
           = lambda self.lambda n.n * self(self)(n - 1)

self_f(self_f) = (lambda self.lambda n.n * self(self)(n - 1))(lambda self.lambda n.n * self(self)(n - 1))
               = lambda n.n * ((lambda self.lambda n.n * self(self)(n - 1)))(((lambda self.lambda n.n * self(self)(n - 1))))(n - 1)

可以看到最终得到的lambda函数仅需要一个参数n

通过增加一个间接层,就可以实现自然的递归

丘奇数

丘奇数都是带两个参数的函数,具体的思路是定义z = 0,然后将s(z)得到z的后继
0 是 lambda s z . z
1 是 lambda s z . s(z)
2 是 lambda s z . s(s(z))


对于 2 + 3 = 5, 我们只需要通过阿尔法和贝塔规约把s(s(z))中的z换为s(s(s(z)))即可

let add = λx y s z.x(s,y(s,z))
let two = λs z.s(s(z))
let three = λs z.s(s(s(z)))

  add(two,three)
= (λx y s z.x(s,y(s,z))) (λs z.s(s(z)),λs z.s(s(s(z))))
= (λs z.(λs z.s(s(z)))(s,(λs z.s(s(s(z))))(s,z)))
= (λs z.(λs z.s(s(z)))(s,s(s(s(z)))))
= (λs z.(λs z.s(s(z)))(s,s(s(s(z)))))
= λs z.s(s(s(s(s(z))))) 

布尔表达式

let TRUE = lambda x y . x 
let FALSE = lambda x y . y
let BoolAnd = lambda x y . x y FALSE 
let BoolOr = lambda x y. x TRUE y 
let BoolNot = lambda x . x FALSE TRUE 
let IfThenElse = lambda cond true_expr false_expr . cond true_expr false_expr 

来个栗子false BoolOr true

  (lambda x y. x TRUE y) (lambda x y . y) (lambda x y . x)
= (lambda x y . y) TRUE (lambda x y . x)
= (lambda x y . x)
= TRUE
posted @ 2022-05-02 09:59  XDU18清欢  阅读(129)  评论(0)    收藏  举报