奇妙的邱奇数

来源:互联网 发布:js获取点击事件的元素 编辑:程序博客网 时间:2024/04/28 13:08

每个人都在描述自己眼中的世界。

 对大家来说自然数真的是再“自然”不过了,我们可以它用来计数,可以用它来做加减乘除运算,一些都是那么自然。自然数是数据,而加减乘除这些处理数据的就被叫做过程,这是大家都公认的,然而数据和过程的界限真的这么清晰吗?一天,一个叫阿隆佐·邱奇的人发明了一种新的计数方式:用lambda算子来描述自然数。这种计数方式被后人称作邱奇数(Church encoding),具体来说就是用过程来描述数据。抛开晦涩的形式定义,我们用代码来一点一点引出邱奇数的定义,由于复杂的lambda表达式难以阅读,因此下面的示例都用的Python代码。

伽利略说过:“给我一个支点,我就能举起地球”。我们只要一个0和一个自增操作就可以表示所有的自然数了,1就是0进行一次自增操作,2就是1进行一次自增操作..... 犹如“鸡生蛋,蛋生鸡,鸡鸡蛋蛋无穷尽也”。同时我们注意到2其实也是0进行两次自增操作

def zero(inc, base):    return basedef one(inc, base):    return inc(base)def two(inc, base):    return inc(inc(base))

其中的zero, one, two就是邱奇数。聪明的你可能已经注意到了,其实邱奇数就是在一个函数g(f,x),自然数n的邱奇数映射就是在x上作用n次f也即是n->fn(x)这样手工来一个一个静态来定义邱奇数太麻烦了,我们需要一个自增操作,那邱奇数的自增操作是什么呢?先看代码

def succ(n):          def res(inc, base):        return inc(n(inc, base))    return res

由于本质上邱奇数是一个函数,因此我们先定义了一个函数res作为succ的返回值。其中n(inc, base)的作用是得到邱奇数n的反映射n'(比如two->2) ,然后再在n'上叠加inc调用,最后我们再把这个函数返回,这样就完成了一次自增的操作。看看效果如何

def inc(n):    return n + 1def _three(inc, base):    return inc(inc(inc(base)))three = succ(two)#equal(_three, three)print two(inc, 0)    # 2 print three(inc, 0)  # 3
如果有一个equal函数来验证的话当然更好(目前我还没有找到验证两个函数相等的方法),在这里我采用了直接带入参数来验证结果。

加法的代码也非常简单

def add(m, n):     return n(succ, m)
我们再回忆一下前面的内容,邱奇数n(inc, base)->n' 的本质就是对base进行n'次inc操作。如果我们的自然数也可以接收参数,那计算2+3就可以表示成这样2(++, 3), 就是用3做base, 进行两次自增,是不是就得到了加法的效果?用这样的思想,我们引出乘法的操作。

小学的时候我们就学了m*n = m + m + m + ..... ,抽象一下:m*n就是在0的基础上进行n次加m操作,结合前面的邱奇数定义我们可以直接写出乘法的操作 

def mult(m, n):    return n(adder, zero)
其中的adder就是加m操作,那怎么表示这个加m操作呢? 在学求偏导数数的时候,我们一般是把一个变量当作自变量,其他的作为常量。这里我们用了同样的方法,把m+n中的m确定

def adder(x):      return add(m, x)
这样我们就得到了一个函数,一个进行加m操作的函数,完整的乘法是这样的

def mult(m, n):     def adder(x):        return add(m, x)    return n(adder, zero)

聪明的你是否已经想到了幂乘的算法了呢?这里我把代码贴出来,看是否和你想的一样

def exp(m, n):     def multer(x):        return mult(m, x)    return n(multer, one)

至此我们已经完成了邱奇数的自增,加法和乘法操作,至于减法和除法操作,有兴趣的同学可以去wiki上看看,这里就不多说了。


在函数是第一公民的语言里,我们有了更广阔的表达能力,数据中蕴含着操作,过程中又蕴含着数据,是不是很类似面向对象呢,sicp的第二章中就用函数描述了一个对象系统。语言也在影响着我们的思考方式,c语言的指针让我们对内存有了灵活的操作,在有垃圾回收的语言中我们可以更专注于业务逻辑,lisp更是可以把自己的代码当作基本的数据来分析,以至于很容易用lisp来写一个自己的解释器.....  路漫漫其修远兮,吾将上下而求索。





	
				
		
原创粉丝点击