Lambda演算前身功能减少步骤

时间:2012-01-09 14:51:59

标签: lambda-calculus reduction

我对lambda演算中的前身函数的维基百科描述感到困惑。

维基百科所说的如下:

PRED:=λnfx.n(λgh.h(g f))(λu.x)(λu.u)

有人可以一步一步解释减少过程吗?

感谢。

5 个答案:

答案 0 :(得分:24)

好的,所以教会数字的概念是用函数编码“数据”,对吧?可行的方法是通过您使用它执行的某些通用操作来表示值。因此,我们也可以走向另一个方向,这有时可以使事情更加清晰。

教会数字是自然数的一元表示。因此,我们使用Z表示零,Sn表示n的后继。现在我们可以计算如下:ZSZSSZSSSZ ...等效的教会数字有两个参数 - 第一个对应{{1} },然后是S的第二个 - 然后使用它们来构造上述模式。所以给定参数Zf,我们可以这样算:xxf xf (f x) ......

让我们来看看PRED的作用。

首先,它创建一个带有三个参数的lambda - f (f (f x))是教会数字,我们想要的前任,当然,这意味着nf是结果数字,这意味着该lambda的主体将被x应用于f,比x少一倍。

接下来,它将n应用于三个参数。这是棘手的部分。

第二个参数,对应于前面的n,是Z - 一个忽略一个参数并返回λu.x的常量函数。

第一个参数,与之前的x相对应,是S。我们可以将其重写为λgh.h (g f),以反映只有最外层的lambda被应用λg. (λh.h (g f))次的事实。此函数的作用是将累积结果带到n并返回一个带有一个参数的新函数,该函数将该参数应用于g应用于g。当然,这绝对令人困惑。

那么......这里发生了什么?考虑使用fS进行直接替换。在非零数字Z中,Sn对应于绑定到n的参数。因此,记住gf绑定在外部范围内,我们可以这样计算:xλu.xλh. h ((λu.x) f) ...执行显而易见的减少,我们得到这个:λh'. h' ((λh. h ((λu.x) f)) f)λu.xλh. h x ......这里的模式是一个函数被“向内”传递到一个层,此时{{1}将应用它,而λh'. h' (f x)将忽略它。因此,对于每个S ,我们会得到一个Z的应用,除了最外层。

第三个参数只是身份函数,由最外面的f尽职尽责地应用,返回最终结果 - S应用的次数少于S层的次数f对应于。

答案 1 :(得分:6)

麦肯的答案解释得很好。让我们举一个具体的例子来说明Pred 3 = 2:

考虑表达式:n(λgh.h(g f))(λu.x)。设K =(λgh.h(g f))

对于n = 0,我们对0 = λfx.x进行编码,因此当我们对(λfx.x)(λgh.h(gf))应用beta缩减时,(λgh.h(gf))将被替换为0次。在进一步降低beta后,我们得到:

λfx.(λu.x)(λu.u)

缩减为

λfx.x

λfx.x = 0,正如所料。

对于n = 1,我们应用K 1次:

(λgh.h (g f)) (λu.x) => λh. h((λu.x) f) => λh. h x

对于n = 2,我们将K应用2次:

(λgh.h (g f)) (λh. h x) => λh. h ((λh. h x) f) => λh. h (f x)

对于n = 3,我们应用K 3次:

(λgh.h (g f)) (λh. h (f x)) => λh.h ((λh. h (f x)) f) => λh.h (f (f x))

最后,我们采用这个结果并对其应用id函数,我们得到了

λh.h (f (f x)) (λu.u) => (λu.u)(f (f x)) => f (f x)

这是数字2的定义。

基于列表的实现可能更容易理解,但需要许多中间步骤。所以它不如教会最初的实施IMO那么好。

答案 2 :(得分:1)

在阅读了之前的答案(好的答案)之后,我想提出自己对此事的看法,希望它可以帮助某人(欢迎更正)。我将使用一个例子。

首先,我想在定义中添加一些括号,使我的一切更加清晰。让我们将给定的公式重新定义为:

PRED := λn λf λx.(n (λgλh.h (g f)) (λu.x)) (λu.u)

让我们定义三个教会数字,这将有助于这个例子:

Zero := λfλx.x
One := λfλx. f (Zero f x)
Two := λfλx. f (One f x)
Three := λfλx. f (Two f x)

为了理解其工作原理,让我们首先关注公式的这一部分:

n (λgλh.h (g f)) (λu.x)

从这里,我们可以得出这样的结论: n是教会数字,要应用的函数是λgλh.h (g f),起始数据是λu.x

考虑到这一点,让我们试一试:

PRED Three := λf λx.(Three (λgλh.h (g f)) (λu.x)) (λu.u)

让我们首先关注数字的缩减(我们之前解释过的部分):

Three (λgλh.h (g f)) (λu.x)

减少到:

(λgλh.h (g f)) (Two (λgλh.h (g f)) (λu.x))
(λgλh.h (g f)) ((λgλh.h (g f)) (One (λgλh.h (g f)) (λu.x)))
(λgλh.h (g f)) ((λgλh.h (g f)) ((λgλh.h (g f)) (Zero (λgλh.h (g f)) (λu.x))))
(λgλh.h (g f)) ((λgλh.h (g f)) ((λgλh.h (g f)) ((λfλx.x) (λgλh.h (g f)) (λu.x)))) -- Here we lose one application of f
(λgλh.h (g f)) ((λgλh.h (g f)) ((λgλh.h (g f)) (λu.x)))
(λgλh.h (g f)) ((λgλh.h (g f)) (λh.h ((λu.x) f)))
(λgλh.h (g f)) ((λgλh.h (g f)) (λh.h x))
(λgλh.h (g f)) (λh.h ((λh.h x) f))
(λgλh.h (g f)) (λh.h (f x))
(λh.h ((λh.h (f x) f)))

结束时:

λh.h f (f x)

所以,我们有:

PRED Three := λf λx.(λh.h (f (f x))) (λu.u)

再次减少:

PRED Three := λf λx.((λu.u) (f (f x)))
PRED Three := λf λx.f (f x)

正如您在减少中看到的那样,由于使用功能的巧妙方式,我们最终将该功能减少一次。

将add1用作f,将0用作x,我们得到:

PRED Three add1 0 := add1 (add1 0) = 2

希望这有帮助。

答案 3 :(得分:0)

您可以尝试在延续方面理解前任函数(不是我最喜欢的函数)的这个定义。

为了简化这个问题,让我们考虑以下变体

    PRED := λn.n (λgh.h (g S)) (λu.0) (λu.u)

然后,你可以用f代替S,用x代替0。

函数的主体在参数N上迭代n次变换M.参数N是类型的函数(nat - > nat) - > nat期望nat的延续并返回nat。最初,N =λu.0,即忽略延续并返回0。 让我们称N为当前计算。

函数M :( nat - > nat) - > nat) - > (nat - > nat) - > nat如下修改计算g:(nat - > nat) - > nat。 它输入一个延续h,并将其应用于 用S继续当前计算g的结果。

由于初始计算忽略了延续,在M的一次应用之后我们得到计算(λh.h0),然后是(λh.h(S 0)),依此类推。

最后,我们将计算应用于身份延续 提取结果。

答案 4 :(得分:0)

我将在上面的解释中加上我的解释,主要是出于我自己的理解。再次是PRED的定义:

PRED := λnfx. (n (λg (λh.h (g f))) )  λu.x λu.u

第一个点右侧的东西应该是应用于x的f的(n-1)个折叠组成:f ^(n-1)(x)。

让我们逐渐了解表达式为什么会是这种情况。

λu.x是x处的常数函数。让我们仅将其表示为const_x。

λu.u是恒等函数。我们称它为id。

λg(λh.h(g f))是我们需要理解的怪异函数。我们称它为F。

好,所以PRED告诉我们在常数函数上评估F的n倍组成,然后在恒等函数上评估结果。

PRED := λnfx. F^n const_x id

让我们仔细看看F:

F:= λg (λh.h (g f))

F将g发送到g(f)的评估值。 让我们用ev_y表示值y的评估。 也就是说,ev_y:=λh.hy

所以

F = λg. ev_{g(f)}

现在,我们找出F ^ n const_x是什么。

F const_x = ev_{const_x(f)} = ev_x

F^2 const_x = F ev_x = ev_{ev_x(f)} = ev_{f(x)}

类似地,

F^3 const_x = F ev_{f(x)} = ev_{f^2(x)}

以此类推:

F^n const_x = ev_{f^(n-1)(x)}

现在

PRED = λnfx. F^n const_x id

     = λnfx. ev_{f^(n-1)(x)} id

     = λnfx. id(f^(n-1)(x))

     = λnfx. f^(n-1)(x)

这就是我们想要的。

超级傻瓜。这个想法是将n次做某事变成f n-1次。解决方案是将F n次应用于const_x以获得 ev_ {f ^(n-1)(x)},然后通过在恒等函数处求值来提取f ^(n-1)(x)。