废话不多说,我们来看看pow_church(m, n)
该如何实现。
这里我们需要计算 mn 。这一次,我们采取另一种办法 —— 先给出解答。
def pow_church(m, n):
"""Return the Church numeral m ** n, for Church numerals m and n.
>>> church_to_int(pow_church(two, three))
8
>>> church_to_int(pow_church(three, two))
9
>>> four = successor(three)
>>> five = successor(four)
>>> church_to_int(pow_church(five, three))
125
"""
"*** YOUR CODE HERE ***"
return n(m)
我想,看到这个答案的时候,你一定和我一样的惊奇。不过,这一个答案其实我是做实现mul_church()
的时候发现的。当时的想法是,既然 church 函数是对实参f
应用(apply / call)n次,那么,n(m)
不就应该是 n * m
了吗?然后结果出乎了我的意料,他是m ** n
。
我们先看看调用pow_church(two, three)
时,究竟施展了什么样的魔法,能够使得结果是m ** n
。
调用pow_church(two, three)
,我们可以得到
eight = lambda f: two(two(two)(f))
这里就让人有些困惑了,我自己都搞晕了呢。仔细看看中间的实参,有个two(two)
。说来有些可笑,闹了这么久,我们貌似没有前进多少。不过,我可不会轻易放弃。
在继续前进之前,让我们往回走几步,再再谈一谈 church 函数到底做了什么事。对于 church_n(f)(x)
,实际将执行f(f(f( .. f(x) .. )))
,一共 n
个 f
。只有理解了这一点,我们才能够明白上面的表达式究竟代表会有什么样令人惊奇的行为。
下面我们先以four = two(two)
为例,按照上面所述的规则,看看他会变成什么模样:
four(f)(x)
two(two)(f)(x)
two(two(f))(x)
two(lambda y: f(f(y)))(x)
# suppose that h(y) = f(f(y))
two(h)(x)
h(h(x))
f(f(f(f(x)))) # four f
注意,这里不是 2×2 ,而是 22 ,应用外层的
two
时,里层翻番了
接下来,eight
最外层的two
又使得 4 个f
翻番,于是得到 8 个f
。至此,花费了如此巨大的力气,我们终于解决了这么一个特例。来之不易啊。
现在,对于任意的 n(m)
与上例一样,对于里层的 m
,我们记
h(x) = f(f( .. f(x) .. ))
共m
个f
于是,
n(m) = h(h( .. h(x) .. ))
共n
个h
总计 m ** n
个 f
。
OK,终于搞定了。
为了证明我还是太菜了,下面给出老师的解答
def one(f):
return lambda x: f(x)
def two(f):
return lambda x: f(f(x))
def church_to_int(n):
return n(lambda x: x + 1)(0)
def add_church(m, n):
return lambda f: lambda x: m(f)( n(f)(x) )
def mul_church(m, n):
return lambda f: m(n(f))
def pow_church(m, n):
return n(m)