我想明白,教会为什么要定义数字:
0 = λ f . λ x . x
1 = λ f . λ x . f x
2 = λ f . λ x . f f x
3 = λ f . λ x . f f f x
4 = λ f . λ x . f f f f x
背后的逻辑是什么?
为什么0表示如下:
0 = λ f . λ x . x
答案 0 :(得分:7)
教会并没有尝试实践。他试图证明关于lambda演算的表达能力的结果 - 原则上任何可能的计算都可以在lambda演算中完成,因此lambda演算可以作为可计算性研究的理论基础。为了做到这一点,有必要将编码数字作为lambda表达式,以便像后继函数这样的东西很容易定义。这是显示lambda演算和Gödel's recursive function theory(它是关于自然数的可计算函数)的等价性的关键步骤。教堂数字基本上是方便的,虽然不是非常可读的数字编码。从某种意义上说,它没有任何非常深刻的逻辑。声明并非本质上<1> λ f . λ x . f x
,而后者是前者的可维护编码。
这并不意味着它是任意编码。它有一个明确的逻辑。编码数字n
的最自然方式是涉及n
。教会数字使用n
函数应用程序。自然数n
由高阶函数表示,该函数将函数n
次应用于输入。 1
由应用一次的函数编码,2
由应用两次的函数编码,依此类推。这是一种非常自然的编码,尤其是在lambda演算的背景下。此外,很容易在它们上定义算术,这简化了lambda演算相当于递归函数的证明。
要在实践中看到这一点,您可以运行以下Python3脚本:
#some Church numerals:
ZERO = lambda f: lambda x: x
ONE = lambda f: lambda x: f(x)
TWO = lambda f: lambda x: f(f(x))
THREE = lambda f: lambda x: f(f(f(x)))
#function to apply these numerals to:
def square(x): return x**2
#so ZERO(square), ONE(square), etc. are functions
#apply these to 2 and print the results:
print(ZERO(square)(2), ONE(square)(2), TWO(square)(2),THREE(square)(2))
输出:
2 4 16 256
请注意,这些数字是通过将数字2分别平方0次,1次,2次和3次获得的。
答案 1 :(得分:6)
根据Peano axioms,对于另一个自然数 n ,自然数为0或 S ( n ):
0 = 0
1 = S(0)
2 = S(S(0))
...
您可以将教会数字视为Peano数字的概括,您可以在其中提供自己的0和 S :
0 = λs.λz. z
1 = λs.λz. s(z)
2 = λs.λz. s(s(z))
...
由于这是一个编程论坛,让我们在EcmaScript 6中创建一些教会数字:
const ZERO = s => z => z;
const ONE = s => z => s(z);
const TWO = s => z => s(s(z));
...
您可以通过提供适当的零和后继来将这些教会数字转换为JavaScript数字:
function toInt(n) {
return n(i => i + 1)(0);
}
然后:
> toInt(TWO)
2
您可以使用教会数字来做一些实际的事情:
function shout(text) {
return text + "!";
}
> shout("hi")
"hi!"
> NINE(shout)("hi")
"hi!!!!!!!!!"
您可以在此处试用:https://es6console.com/iyoim5y8/
答案 2 :(得分:2)
以下paper由Robert (Corky) Cartwright为我打破了它。
从一开始就要掌握的要点:
f
- 是“继承者”功能(即接受教会数字并返回教会数字旁边的教会数字,它基本上是增量); x
- 是一个(教会数字)值,表示“零”(计数起点)。牢记这一点:
λf . λx . x
如果我们将传递适当的f
('后继'' - 增量函数)和x
('零' - 计数起点),将等于零。 在这种特殊情况下,将f
传递给哪个函数并不重要,因为它从未应用:
λf . λx . ZERO
这样:
λf . λx . fx
将评估为1:
λf . λx . INCREMENT ZERO
以及以下内容:
λf . λx . f f x
将符合2:
λf . λx . INCREMENT(INCREMENT ZERO)
等等,对于所有连续的数字。
奖金(教会数字的加法,乘法和取幂):
这是一个Python代码片段,用于说明(并展开)上述内容:
ZERO = lambda f: lambda x: x
ONE = lambda f: lambda x: f(x)
TWO = lambda f: lambda x: f(f(x))
THREE = lambda f: lambda x: f(f(f(x)))
SUCC = lambda x: x + 1
ADD = lambda f: lambda x: lambda n: lambda m: n(f)(m(f)(x))
MULT = lambda f: lambda x: lambda n: lambda m: n(m(f))(x)
EXPON = lambda m: lambda n: n(m)
ADD
利用了这样一个事实:任何教会数字都接受一个'零'计数起点,因为它的论点 - 从n
开始,它只计入m
。因此,ADD(SUCC)(0)(THREE)(TWO)
只会计为3,但从2开始,因此会给我们2 + 1 + 1 + 1 = 5
。
MULT
利用了这样一个事实,即“后继”函数只是教会数字的一个参数,因此可以被替换。因此,MULT(SUCC)(0)(TWO)(THREE)
将返回3两次,这与2 * 3 = 6
相同。
EXPON
有点棘手(至少对我自己来说),关键的点是跟踪什么是返回的内容。它基本上是什么 - 使用教会数字表示的内在机制(特别是f
应用的递归)。以下是一些例子:
3 0
EXPON(THREE)(ZERO)(SUCC)(0)
↓
lambda n: n(THREE)(ZERO)(SUCC)(0)
↓
ZERO(THREE)(SUCC)(0)
↓
lambda x: (SUCC)(0)
↓
SUCC(0)
↓
1
3 1
EXPON(THREE)(ONE)(SUCC)(0)
↓
lambda n: n(THREE)(ONE)(SUCC)(0)
↓
ONE(THREE)(SUCC)(0)
↓
lambda x: THREE(x)(SUCC)(0)
↓
THREE(SUCC)(0)
↓
3
1 3
EXPON(ONE)(THREE)(SUCC)(0)
↓
lambda n: n(ONE)(THREE)(SUCC)(0)
↓
THREE(ONE)(SUCC)(0)
↓
lambda x: ONE(ONE(ONE(x)))(SUCC)(0)
↓
ONE(ONE(ONE(SUCC)))(0)
↓
ONE(ONE(lambda x: SUCC(x)))(0)
↓
lambda x:(lambda x: (lambda x: SUCC(x)) (x))(x)(0)
↓
SUCC(0)
↓
1