首页 技术 正文
技术 2022年11月22日
0 收藏 370 点赞 2,409 浏览 2354 个字

先约定几个记号:

  1. 定义用一个冒号加等号表示“:=”,
  2. 表达式全等用两个等号表示“==”,
  3. 归约意义上的相等用一个等号表示“=”,“==”蕴涵“=”。

由于lambda演算不能定义符号,所以像这样的递归定义是不能被求值的:

f := (lambda () (f))

如何在lambda验算中实现递归?从最简单的递归函数开始。希望能带来一些启发。

寻找 \(\Omega\)

首先,我们的目标是找出一个无限循环的lambda表达式。另外额外要求这个表达式最短。

一个lambda表达式只可能有三种形式:

  1. 符号(x, y, z等等),
  2. 函数(如(lambda (x) x)),
  3. 应用(英文application,即函数调用,如调用函数func,参数x写作:(func x))。

第1、2种形式又称为值(value),因为他们不能被归约了。一个无限循环的表达式只能是第3种形式:

(exp1 exp2)

考虑exp1。exp1是个函数,或者能被归约成函数的应用。如果exp1是应用,那么exp1要么会归约到一个函数,要么无限循环。如果exp1无限循环,就和我们的最短假设矛盾,所以exp1会归约到一个函数。如果exp1会归约到一个函数,那么和exp1是一个函数没什么区别。简单考虑,假设exp1是个函数:

exp1 := (lambda (x) body)

那么

(exp1 exp2)
== ((lambda (x) body) exp2)
= body[x <- exp2]

为了让表达式无限循环,我们希望:

(exp1 exp2) == body[x <- exp2]

所以body应该是个应用:

body := (subexp1 subexp2)
<=> (exp1 exp2) == (subexp1[x <- exp2] subexp2[x <- exp2])
<=> exp1 == subexp1[x <- exp2]  and  exp2 == subexp2[x <- exp2]

从最后一个条件可以推出:

exp2 == subexp2[x <- exp2]  <=>  subexp2 == x

另外还能看出,表达式exp1中包含了一个和exp2相等的子表达式。满足这个条件的最简单的exp1就是和exp2相等的exp1。

exp1 == exp2
<=> subexp1[x <- exp2] == exp2
<=> subexp1 == x

综合几个条件:

exp1
== (lambda (x) body)
== (lambda (x) (subexp1 subexp2))
== (lambda (x) (x x))exp2
== exp1
== (lambda (x) (x x))

于是我们要找的无限循环的表达式是:

((lambda (x) (x x)) (lambda (x) (x x)))

这个表达式就是lambda演算里的\(\Omega\)表达式。\(\Omega\)表达式循环的关键在于(f f)形式的表达式,即自己应用到自己。\(\Omega\)包含了三个(f f)形式的表达式。

寻找 Y combinator

一般来说,递归函数长这个样子:

target := (lambda args body[target])

body[target]的意思是一个包含target这个符号的表达式,args表示这是一个任意个数参数的函数。在这个表达式中,target是一个无约束的符号。一个包含无约束符号的表达式不能被求值。Lambda演算中约束一个符号的方法是用lambda关键字,为了让target变成约束符号,我们改写表达式:

p := (lambda (target)
(lambda args body[target]))
   = (lambda (f)
       (lambda args body[f]))

为了避免混淆,上面将target改名成f(\(\alpha\)归约),target仍然表示我们想要的递归函数的表达式。target和p有如下关系:

(p target)
= (lambda args body[target])
= target

顺便一提,可以看出我们在寻找的target是p的一个不动点。

接下来考虑如何找target。记得寻找\(\Omega\)的启发吗?我们猜测target是一个(g g)形式的表达式:

target == (g g)
=>
(p target) = target
<=> (p (g g)) = (g g)
<=> (g g) = (p (g g)) = ((lambda (x) (p (x x))) g)

根据最后一个条件可以看出:

g := (lambda (x) (p (x x)))
=>
target == (g g)
== ((lambda (x) (p (x x)))
(lambda (x) (p (x x))))

把p提取到参数位置:

target =
((lambda (f)
((lambda (x) (f (x x)))
(lambda (x) (f (x x))))) p)Y :=
(lambda (f)
((lambda (x) (f (x x)))
(lambda (x) (f (x x)))))target = (Y p)

这个Y就是Y combinator。

用 Y combinator 推导出 \(\Omega\)

最简单的无限循环函数是:

f := (lambda () (f))

利用Y combinator来生成这个函数的lambda表达式看看会得到什么?

(Y (lambda (f) (lambda () (f))))
= ((lambda (x) ((lambda (f) (lambda () (f))) (x x)))
(lambda (x) ((lambda (f) (lambda () (f))) (x x))))
= ((lambda (x) (lambda () ((x x))))
(lambda (x) (lambda () ((x x)))))

呼,要对齐这么多括弧真不容易。注意到(\(\eta\)归约):

(lambda () ((x x))) = (x x)

所以:

(Y (lambda (f) (lambda () (f))))
= ((lambda (x) (x x)) (lambda (x) (x x)))
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,082
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,557
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,406
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,179
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,815
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,898