为什么定义丘奇数词

Why the definition of Church's Numerals

我想明白,为什么教会定义这样的数字:

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

Church 并没有试图变得实用。他试图证明关于 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

请注意,这些数字是分别将数字两个0次、1次、2次和3次的平方得到的。

根据Peano axioms,一个自然数要么是0,要么是S(n)另一个自然数n:

0 = 0
1 = S(0)
2 = S(S(0))
...

您可以将教会数字视为皮亚诺数字的概括,您可以在其中提供自己的 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/

下面的paper by Robert (Corky) Cartwright对我来说很好分解。

一开始要掌握的要点:

  • 所有丘奇数都是带两个参数的函数;
  • 在任何数字的教会表示中,都暗示:
    • f — 是 'successor' 函数(即接受一个教会数字和 returns 教会数字的函数, 它基本上是和增量);
    • x — 是一个(教会数字)值,表示 'zero'(计数起点)。

记住这一点:

λf . λx . x

将等于零,如果我们将传递适当的 f ('successor' — 增量函数)和 x ('zero' — 计数起点)。 在这种特殊情况下,什么函数将作为 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 利用了这样一个事实,即任何教会数字都接受 'zero' 计数起点,因为它是参数——它只从 m 开始计数到 ​​n。所以,ADD(SUCC)(0)(THREE)(TWO) 只会数到 3,但从 2 开始,因此我们得到 2 + 1 + 1 + 1 = 5.

MULT 利用了一个事实,即 'successor' 函数只是一个 Church 数字的参数,因此可以被替换。因此 MULT(SUCC)(0)(TWO)(THREE) 将 return 3 两次,这与 2 * 3 = 6.

相同

EXPON 有点棘手(至少对我自己来说是这样),这里的关键 点是要跟踪 return 被什么[编辑的内容] =86=]。它基本上所做的是使用 Church 数字表示的内在机制(特别是 f 应用程序的递归)。下面举几个例子来说明:

30

EXPON(THREE)(ZERO)(SUCC)(0)
↓
lambda n: n(THREE)(ZERO)(SUCC)(0)
↓
ZERO(THREE)(SUCC)(0)
↓
lambda x: (SUCC)(0)
↓
SUCC(0)
↓
1

31

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

13

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