负暄琐话

我的email: rot47('649@ 6(hF+`hd"w=92vhG{>}G3"@l M >:>6?4@56 \F')

用户操作
[即时聊天] [发私信] [加为好友]
g9ID:g9yuayon
924041次访问,排名35好友47人,关注者46
姓名:g9yuayon
前世:夜郎国厚脸皮神棍
魅力指数:0
名气:1
宠物:一只从来不对生人叫的看门狗
g9yuayon的文章
原创 244 篇
翻译 4 篇
转载 50 篇
评论 912 篇
g9的公告
最近评论
fferror:g9大大,最后一个C版本的SQUARE(x)是不是有错? 等待回复。
neilton:嘿嘿
neilton:嘿嘿
duguguiyu1984:老大邪恶了。。。呵呵。。。
xingranliuyun:我感觉到这两个人的灵魂就像最后的那段音乐一样,自由、奔放。

我燃了!
文章分类
收藏
    相册
    旅游
    计算机科学
    Lambda the Ultimate
    软件开发
    Reddit编程专栏(RSS)
    正在读的书
    存档
    订阅我的博客
    XML聚合  FeedSky

    翻译 lambda算子3:阿隆佐.丘齐(Alonzo Church)的天才收藏

    新一篇: lambda算子3:阿隆佐.丘齐(Alonzo Church)的天才 | 旧一篇: 行为艺术家黎鸣老师

    lambda算子3

    阿隆佐.丘齐(Alonzo Church)的天才:Lambda算子里的数

    前面建立了lambda运算的基本规则,就可以用lambda算子做点有意思的东西了。开始前为方便计,我们先来点语法糖花差花差,用来命名函数。这些语法糖可以让复杂的公式好写一点。

    我们用"let" 来引入一个“全局”函数(也就是说,我们用这个函数时,不用在每个表达式里定义一次):
    let squer = lambda x. x^2

    这个式子申明了一个叫"square"的函数,定义为 lamdba x. x^2。如果我们有一个表达式 "square 4",上面的"let"意味着这个表达式和下面这个表达式一样:
    (lambda square. square 4)(lambda x. x^2)。这个"let"是从Common Lisp或者Scheme里借来的。Lambda算子里可没有这个东西。数学家推崇“如无必要,毋增实体”。这些关键字不入他们的法眼。不过对写惯了程序的我们来说,这些句法糖就可爱多了。

    我们的例子里会用到数字和算术操作符。不过记住lambda算子里根本没有数字。我们只有函数!所以我们需要发明用函数来创造数字的方法。幸好Alonzo Church是个天才。他既然发明了lambda算子,用lambda算子表征数字自然不在话下。他搞出的用于数字的函数自然就叫做丘齐数(Church Numerals)。

    丘齐数里,所有的数字都是两个参数的函数:

    1. 零是 lambda s z . z
    2. 一是 lambda s z . s z
    3. 二是 lambda s z . s (s z)
    4. 对任意一个数"n",它的丘齐数都是一个函数。这个函数把它的第一个参数应用到第二个参数上n次。用流行的写法,就是lambda s z . s sn z。 绕口啊绕口。做形式化的东东不幸之处就是成天和绕口令打交道。解脱这道呢?当然就是牢记牛人费因曼在Connection Machine工作时的学习方法:问最简单的问题。“给我最简单的例子”。“怎么才能验证这是正确的?”。
      比如说零(lambda s z . z)吧,第一个参数是s, 应用零次就是没有,所以函数体就是孤零零的"z"。那数字一呢?当让就是把第一个参数,s,应用到z上一次,所以函数体就变成了"s z"。

    理解这个定义的方法之一时把"z"看作丘齐数里零的名字,而把"s"看后继函数(successor function)的名字。“后继函数”其实很简单,C/C++里的++是也。所以呢,零就是一个返回"0"这个值的函数;一就是把后继函数应用到零上一次的函数;二就是把后继函数应用到一上一次或者说零上两次的函数。0++ 得到 1, 1++ 等价与(0++)++,而1++得到2.现在把0换成z,把++换成s, 一切就清楚了。


    现在--看好了。如果我们想做加法,x+y,我们需要一个带4个参数的函数。两个参数代表相加的两个数字,以及为得到结果而需要的"s"和"z"。

    let add = lambda s z x y . x s (y s z)

    看着好像有点不知所云。不过我们可以用Curry这个利器,分开"s" "z"和x, y。首先,Curry后得到的函数带两个参数,x和y(这个好比add(x, y),符合我们对加号的理解)。其次,我们需要正规化x和y需要的s和z,让x和y共享相同的零和后继函数的绑定:

    let add = lambda x y. (lambda s z . (x s (y s z)))

    仔细观察一下,上面的式子无非是说,要把x和y相加,我们先用"s"和"z"创建丘齐数"y",然后在把"x"应用到y上。应用时需要的"s"和"z"是"y"里的"s"和"z"。也就是说,我们的到的结果是一个函数,这个函数把自己加到另一个函数上。还是用例子来说明问题。比如说2+3:

    add (lambda s z. s (s z)) (lambda s z . s (s (s z))) news newz

    为了让演算变得稍微容易一点,我们先对2和3来个Alpha转换。让2用s2和z2,而3用s3和z3:

    add (lambda s2 z2 . s2 (s2 z2)) (lambda s3 z3 . s3 (s3 (s3 z3)))

    现在我们可以把"add"替换成它的定义了:

    (lambda x y .(lambda s z. (x s y (s z)))) (lambda s2 z2 . s2 (s2 z2)) (lambda s3 z3 . s3 (s3 (s3 z3))) 

    现在可以对"add"用beta变换了(温馨提示:也就是把形参x和y换成对应的实参):

    lambda s z . (lambda s2 z2 . s2 (s2 z2)) s (lambda s3 z3 . s3 (s3 (s3 z3)) s z)


    然后我们可以对3这个丘齐数做beta转换。这步操作其实是“正规化”3:把3的定义里的后继函数和零函数(还记得零是个函数吧?)替换成add的参数列表里的后继函数和零函数:

    lambda s z . (lambda s2 z2 . s2 (s2 z2)) s (s (s (s z)))

    嗯,有点眉目了。现在是真正漂亮的地方了。再来次对2的Beta变换。看看我们准备做什么:2是个带两个参数的函数:一个参数是后继函数,另一个是零函数。要把2加到3上,我们只需要用到"add"这个函数的后继函数。也就是说,我们把计算了3后的结果当成零函数的值!

    lambda s z . s (s (s (s (s z)))

    而这个式子,正是丘齐数5!

    丘齐数酷的地方是它抛弃了传统整数的概念,用函数取而代之。它把每个数对应为一个函数。而数数(counting)这个操作被对应为应用某个函数(在这里是后继函数)的次数。当然了,上面的介绍非常简单。对丘齐数感兴趣的,可以看这篇文章

    丘齐数对编程有什么用嗫?俺还真不知道。但丘齐数(进而到丘齐编码)确实一系列基础理论中有重要应用,比如说有类型的lambda算子。不过这点重要吗?不重要吗?重要吗?不重要吗?研究研究嘛。

    发表于 @ 2006年08月14日 14:45:00|评论(loading...)|编辑

    新一篇: lambda算子3:阿隆佐.丘齐(Alonzo Church)的天才 | 旧一篇: 行为艺术家黎鸣老师

    评论

    #albertlee 发表于2006-09-12 16:01:00  IP: 222.128.7.*
    看到这里真是晕了……

    不过看到最好 lambda s z . s (s (s (s (s z))) 这个结果真是击掌叫好阿。
    #baikaishiuc 发表于2008-03-08 22:24:35  IP: 125.71.4.*
    理解这个定义的方法之一时把"z"看作丘齐数里零的名字,而把"s"看后继函数(successor function)的名字。“后继函数”其实很简单,C/C++里的++是也。所以呢,零就是一个返回"0"这个值的函数;一就是把后继函数应用到零上一次的函数;二就是把后继函数应用到一上一次或者说零上两次的函数。0++ 得到 1, 1++ 等价与(0++)++,而1++得到2.现在把0换成z,把++换成s, 一切就清楚了。

    在这一段中,假如你是用c/c++里面的++来加强说明的话,那么我觉的后面的0++,1++改成++0, ++1更好些。

    现在我们可以把"add"替换成它的定义了:

    (lambda x y .(lambda s z. (x s y (s z)))) (lambda s2 z2 . s2 (s2 z2)) (lambda s3 z3 . s3 (s3 (s3 z3)))

    另外这个地方中的第二个lambda表达式中的 y 该放到它右边的那个括号内。

    我也是今天刚看你的文章开始学习lambda,说的不对请指正。另外想问下,这个东西学起来是干什么的?我曾经看过些关于图灵机的文章感觉有点像,对学习计算机系统有什么帮助吗?
    2008-03-12 20:33:26作者回复
    是滴。是滴。谢谢指出。
    #greenar 发表于2008-04-01 08:22:56  IP: 135.251.125.*
    老大,你的表示法很费劲啊
    看到这里
    http://homepages.nyu.edu/~cb125/Lambda/
    虽然是E文,还是好懂一点
    add:
    lambda M.lambda N. lambda f. lambda x. N f(M f x)

    multiplication:
    lambda M.lambda N. lambda f. lambda x. N(M f)x

    另外看到这里
    http://www.cs.rice.edu/~javaplt/311/Readings/supplemental.pdf
    提到Exponentiate,我解了一下,不知道对不对
    Cn•Cn = lambda f x. Cn(Cn f)x
    Cn•Cn•Cn=Cn•lambda f x. Cn(Cn f)x
    =lambda f x. (lambda f1 x1.Cn (Cn f1) x1)(Cn f)x
    =lambda f x. Cn (Cn (Cn f)x

    Cn^Cm = lambda f x.Cn(Cn... (Cn f)x
    2008-04-01 17:03:14作者回复
    呵呵。这个是翻译别人的(前面注明了滴)。不过我觉得挺明白的阿。可能我个人口味比较怪异。:-)
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © g9