简体   繁体   English

Lambda演算Beta还原的具体步骤以及原因

[英]Lambda calculus beta reduction specific steps and why

From a book I'm recently reading: 从我最近读的一本书中:

First: 第一:

𝜆𝑧.(𝜆𝑚.𝜆𝑛.𝑚)(𝑧)((𝜆𝑝.𝑝)𝑧) The outermost lambda binding 𝑧 is, at this point, irreducible because it has no argument to apply to. 𝜆𝑧.(𝜆𝑚.𝜆𝑛.𝑚)(𝑧)((𝜆𝑝.𝑝)𝑧)在这一点上,最外面的lambda绑定是不可约的,因为它没有适用于自变量的参数。 What remains is to go inside the terms one layer at a time until we find something reducible. 剩下的就是每次进入术语一层,直到我们找到可简化的东西。

Next: 下一个:

𝜆𝑧.(𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧) We can apply the lambda binding 𝑚 to the argument 𝑧. 𝜆𝑧.(𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧)我们可以将lambda绑定𝑚应用于自变量𝑧。 We keep searching for terms we can apply. 我们一直在寻找可以申请的条款。 The next thing we can apply is the lambda binding 𝑛 to the lambda term ((𝜆𝑝.𝑝)𝑧) . 我们接下来要应用的是将lambda绑定𝑛到lambda项((𝜆𝑝.𝑝)𝑧)

I don't get it. 我不明白 In the first section, it says 𝜆𝑧 has no argument to apply to, that I can probably understand, but then at the Next section I think the z can be bound to ((𝜆𝑝.𝑝)𝑧) because as you can see, 𝜆𝑧.(𝜆𝑛.𝑧) , the body of 𝜆𝑧 clearly has a z argument which can be bound. 在第一部分中,我说𝜆𝑧可能没有𝜆𝑧适用,但是在下一部分中,我认为z可以绑定到((𝜆𝑝.𝑝)𝑧)因为如您所见, 𝜆𝑧.(𝜆𝑛.𝑧)身体𝜆𝑧显然有z可以绑定参数。 But the book just ignored the head 𝜆𝑧 and directly bound n to ((𝜆𝑝.𝑝)𝑧) . 但是这本书只是忽略了头部𝜆𝑧并将n直接绑定到((𝜆𝑝.𝑝)𝑧) I mean 𝜆𝑛.𝑧 doesn't have an n argument, why does it get to be bound? 我的意思是𝜆𝑛.𝑧没有n参数,为什么要绑定它?

Can somebody explain to me about this? 有人可以向我解释一下吗?

Using normal order evaluation, you can get the answer in two beta reductions 使用正常订单评估,您可以得到两个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

The second reduction might seem tricky because n is bound to ((λp.p)z) but the expression is just z , so n is thrown away. 第二个减少似乎很棘手,因为n绑定到((λp.p)z)但表达式只是z ,所以n被扔掉了。


Using applicative order evaluation, it takes one extra step 使用应用订单评估,需要多执行一步

// 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

In this scenario, whether we use normal order evaluation or applicative order evaluation, the result is the same. 在这种情况下,无论我们使用常规订单评估还是应用订单评估,结果都是相同的。 Differing evaluation strategies sometimes evaluate to different results. 不同的评估策略有时会评估不同的结果。

An important note, the reduction steps we've done above will not take place until λz is applied (depending on the implementation). 一个重要的注意,我们之前所做的那样,直到不会发生还原步骤λz应用(取决于实现)。 In the example code you have provided, λz is never applied, therefore simplifying λz 's term is just for exercise, in this case. 在您提供的示例代码中,从未应用λz ,因此在这种情况下,简化λz的术语仅是为了练习。

All we've done is demonstrate lambda equivalence (under two different evaluation strategies) 我们所做的只是证明了lambda的等效性 (在两种不同的评估策略下)

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

Lambda notation is a bit weird to parse. Lambda表示法有点奇怪。 IMO Haskell syntax is clearer: IMO Haskell语法更清晰:

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

or, even more explicit 或者,甚至更明确

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

The first reduction step is 第一步减少是

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

or 要么

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

then you can indeed bind ((\\p -> p) z) – not to z but to n ! 那么您确实可以绑定((\\p -> p) z) –不是绑定到z而是绑定到n (Which isn't actually used at all though.) (实际上根本没有使用。)

\z -> (
        (z)
      )

or simply \\z -> z . 或者只是\\z -> z So, we still have that z lambda, which as the book said is irredicible. 因此,我们仍然拥有z lambda,正如书中所说,这是不可思议的。 We just don't have anything else! 我们别无其他!


...I'm not sure if that was actually your question. ...我不确定这是否真的是你的问题。 If it was rather: why must we not first see if we can reduce ((\\p -> p) z) , then the answer is, I think, lambda calculus as such doesn't define this at all (it just defines what transformation you can apply, not in which order you should do it. Actually I'm not sure about this, correct me if I'm wrong ). 如果是这样:为什么我们不首先要看是否可以减少((\\p -> p) z) ,那么我认为答案是lambda微积分根本没有定义这一点(它只是定义了什么您可以应用转换,而不应该按照顺序进行转换。 实际上,我对此不确定,如果我错了,请更正 In a strict language like Scheme, you would indeed first reduce ((\\p -> p) z) ; 在像Scheme这样的严格语言中,您确实确实会首先减少((\\p -> p) z) Haskell wouldn't do that since there's no need. Haskell不会这样做,因为没有必要。 Either way, it doesn't really matter, because the result is discarded anyway. 无论哪种方式,都没有关系,因为结果还是被丢弃了。

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

The key is that n is never used in the abstraction. 关键是抽象中永远不要使用n n is still bound to ((λp.p)z) , but it is immediately discarded. n仍然绑定到((λp.p)z) ,但立即将其丢弃。

λz.(λm.λn.m)(z)((λp.p)z) = λz.(λn.z)((λp.p)z)  Replacing m with z
                         = λz.z                Replacing n with ((λp.p)z)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM