Lambda演算β减少具体步骤和原因

时间:2016-08-10 17:58:14

标签: haskell lambda functional-programming lambda-calculus

从我最近阅读的一本书中读到:

首先:

.(..)()((.)) 在这一点上,最外层的lambda绑定是不可简化的,因为它没有适用的参数。剩下的就是一次进入一个层面,直到找到可以减少的东西。

下一步:

.(.)((.)) 我们可以将lambda绑定应用于参数。我们一直在寻找可以申请的条款。接下来我们可以应用lambda绑定到lambda术语((.))

我不明白。在第一部分中,它说没有适用的参数,我可能理解,但是在下一部分我认为z可以绑定到((.)),因为你可以看到,.(.)的主体明显有一个z参数可以绑定。但是这本书忽略了头部并将n直接绑定到((.))。我的意思是.没有n参数,为什么会被绑定?

有人可以向我解释一下吗?

3 个答案:

答案 0 :(得分:5)

使用正常的订单评估,您可以获得两次beta减少的答案

// beta reduction 1
λz.(λm.λn.m)(z)((λp.p)z) →β (λn.m) [m := z]
λz.(λm.λn.z)(z)((λp.p)z)

// beta reduction 2
λz.(λn.z)((λp.p)z)       →β z      [n := ((λp.p)z)]
λz.(λn.z)((λp.p)z)

// result
λz.z

第二次缩减可能看起来很棘手,因为n绑定到((λp.p)z)但表达式只是z,因此n被丢弃。

使用应用程序订单评估,需要一个额外的步骤

// beta reduction 1
λz.(λm.λn.m)(z)((λp.p)z) →β p      [p := z]
λz.(λm.λn.m)(z)((λp.z)z)

// beta reduction 2
λz.(λm.λn.m)(z)(z)       →β (λn.m) [m := z]
λz.(λm.λn.z)(z)(z)

// beta reduction 3
λz.(λn.z)(z)             →β z      [n := z]
λz.(λn.z)(z)

// result
λz.z

在这种情况下,无论我们使用正态订单评估还是应用订单评估,结果都是相同的。不同的评估策略有时会评估不同的结果。

重要提示,我们在上面执行的缩减步骤不会发生,直到 λz被应用(取决于实现)。在您提供的示例代码中,永远不会应用λz,因此在这种情况下,简化λz的术语仅适用于练习。

我们所做的就是展示lambda 等价(在两种不同的评估策略下)

λz.(λm.λn.m)(z)((λp.p)z) <=> λz.z

答案 1 :(得分:4)

Lambda表示法解析有点奇怪。 IMO Haskell语法更清晰:

\z -> (\m -> \n -> m) z ((\p -> p) z)

或者,更明确的

\z -> (
        (
           ( \m -> (\n -> m) )
           z
        )
        ( (\p -> p) z )
      )

第一个减少步骤是

\z -> (
        (
           (\n -> z)
        )
        ( (\p -> p) z )
      )

\z -> (
        (\n -> z)
        ( (\p -> p) z )
      )

然后你确实可以绑定((\p -> p) z) - 不是z而是绑定n! (但实际上并没有使用它。)

\z -> (
        (z)
      )

或只是\z -> z。所以,我们仍然拥有z lambda,正如本书所说的那样是不可预测的。我们什么都没有!

......我不确定这实际上是你的问题。如果它是相反的:为什么我们必须首先看看我们是否可以减少((\p -> p) z),那么答案是,我认为,lambda演算本身并没有定义这个(它只是定义你可以应用的转换,而不是你应该这样做的顺序。实际上我不确定这个,如果我错了,请纠正我< / SUP>)。在像Scheme这样严格的语言中,你的确会先减少((\p -> p) z); Haskell不会这样做,因为没有必要。无论哪种方式,它都无关紧要,因为无论如何都会丢弃结果。

   ( \z -> (\n -> z) ((\p -> p) z) )
≡  ( \z -> (\n -> z) z )
≡  ( \z -> (\n -> z) foo )
≡  ( \z -> z )

答案 2 :(得分:0)

关键是 n 从未在抽象中使用。 <{1}}仍然绑定到n,但会立即丢弃。

((λp.p)z)
相关问题