x
中没有(lambda (x) x)
。没有任何。
里面x
是绑定的。它可以用任何名称命名。我们不能谈论in ,就像我们不能谈论in一样。(lambda (x) x)
x
(lambda (x) x)
y
(lambda (y) y)
没有什么可说的y
。(lambda (y) y)
它只是一个占位符,一个任意名称,其在正文中的唯一用途是与活页夹中的相同。相同,只要使用两次即可,不考虑使用哪个特定名称-第一次在活页夹中,另一次在正文中。
事实上,对于 lambda 项还有一个完整的“另一种表示法”,称为 De Bruijn 表示法,其中写的是相同的全部(lambda 1)
内容。1
意思是,“我指的是我上面一级的活页夹收到的论据” 。
所以x
不重要。重要的是(lambda (x) x)
它表示一个按原样返回其参数的函数。所谓的“身份”功能。
但即使这在这里也不重要。数字的 Church 编码实际上是一个二进制函数,一个需要两个参数的函数—— thef
和 the z
。“后继步骤”一元函数f
和“零”“值” z
,无论是什么,只要两者结合在一起。一起有意义。一起工作。
那么,当它实际上是一个二元函数时,我们怎么会在那里看到两个一元函数呢?
这是重要的一点。它被称为柯里化。
在 lambda 演算中,所有函数都是一元的。为了表示一个二元函数,使用一元函数,这样当给定它的(第一个)参数时,它返回另一个一元函数,当给定它的(现在,第二个)参数时,它执行我们预期的二元函数应该执行的任何事情,使用这两个参数,第一个和第二个。
如果我们只是用组合(等式)表示法而不是 lambda 表示法来编写它,这一切都非常非常简单:
zero f z = z
one f z = f z
two f z = f (f z) = f (one f z) = succ one f z
succ one f z = f (one f z)
其中每个并列表示一个应用程序,所有应用程序都在左侧关联,所以我们想象上面是一个快捷表示法
zero f = lambda z. z
zero = lambda f. (lambda z. z)
......
......
succ = lambda one. (lambda f. (lambda z. f (one f z) ))
;; such that
succ one f z = (((succ one) f) z)
= ((((lambda one. (lambda f. (lambda z. f (one f z) ))) one) f) z)
= ....
= (f ((one f) z))
= f (one f z)
但这是同一回事。符号的差异并不重要。
当然也没有one
in lambda one. (lambda f. (lambda z. f (one f z) ))
。它是绑定的。它可能只是命名,我不知道,number
:
succ number f z = f (number f z) = f ((number f) z)
意义,(succ number)
是这样一个数字, 给定f
和z
, 与它们相比, 与它们相比, 多f
一步number
。
因此,((zero square) 100)
意味着,使用zero
带有后继步骤的数字square
和 的零值100
,并zero
为我们执行其后继步骤的数量 - 也就是说,0步骤 - 从零值开始。因此返回它不变。
另一种可能的用途是((zero (lambda (x) 0)) 1)
,或一般来说
((lambda (n) ((n (lambda (x) 0)) 1)) zero)
;; or even more generally, abstracting away the 0 and the 1,
((((lambda (n) (lambda (t) (lambda (f) ((n (lambda (x) f)) t)))) zero) 1) 0)
这只是另一种写作方式
zero (lambda x. 0) 1 ;; or
foo n t f = n (lambda x. f) t ;; and calling
foo zero 1 0
foo
希望你能很容易地看到是什么。还有如何大声朗读这个t
和这个f
。(可能原件f
会更好地命名s
为“继任者”或类似的名称)。