高阶函数和church计数
在SICP的第二章的2.06有一个church计数的题目,非常有意思。 题目是这样的:
定义0为:
(define zero (lambda (f) (lambda (x) x)))定义加一操作为:
(define (add1 n) (lambda (f) (lambda (x) (f ((n f) x)))))
给出1和2的定义。
one就是(add-1 zero),为:
(lambda (f) (lambda (x) (f x)))
one跟zero的差别就是对x多了一次f处理,可以猜一下,two应该是:
(lambda (f) (lambda (x) (f (f x))))
tow就是对x做了2次f处理。如果用替换模型,结果也确实如此。
按照这个模型,用church计数方法,整数n应该有n个f:
(lambda (f) (lambda (x) (f (f ... (f (f x))))
题目提出要实现church计数的加法,两个church计数相加:
(add n1 n2)
就是f函数的次数相加。
例如one和two相加,就是要把(f x) + (f (f x))弄成 (f (f (f x)))。
可以看到,如果能把(f x)中的x换成(f (f x))就可以了。而
(f (f x)) = ((lambda (x) (f (f x))) x) = (((lambda (f) (lambda (x) (f (f x)))) f) x) = ((two f) x)
那要把n2加到n1上,就是
(f ((two f) x)) = ((one f) ((two f) x))
最后加上f和x的参数,就成了:
(lambda (f) (lambda (x) ((one f) ((two f) x))))
所以church计数的加法就是
(define (add n1 n2) (lambda (f) (lambda (x) ((n1 f) ((n2 f) x)))))
church计数看上去没什么用,但是如果实现了church计数的加法,可以得到对函数的重复调用的高阶函数。