问题
Given the following lambda expression, where \
resembles lambda
:
(\kf.f(\c.co)km)(\x.dox)(\le.le)
Is it wrong if I convert (\c.co)k
into ko
? I did that and apparently, it was wrong. The right way to go would have been to evaluate the outer function first, meaning (\f.f(\c.co)(\x.dox)m)(\le.le)
would have been the desired solution.
Is that true, because I can't find any rule that could indicate that in our lecture notes? If yes, why can't I evaluate inner functions first? I've done it like this and my solution was correct, nonetheless.
Regards.
回答1:
I asked my TA, he said that application is left associative, meaning
(\kf.f(\c.co)km)(\x.dox)(\le.le)
is equivalent to
( [\kf.( [ f(\c.co) ]k )m ][\x.dox] )[ \le.le ]
That explains why k
can't be applied to (\c.co)
.:/
Brackets/parentheses are used only to make it more readable.
Regards.
回答2:
So, beta-reduction in the (untyped) lambda calculus is what we call a confluent rewrite rule. This means if you can rewrite A
to B
with beta reduction, and also rewrite A
to C
with beta-reduction, then you can find some D
such that B
rewrites to D
and C
rewrites to D
- there will be, in effect, some common descendent. The theorem that shows this for the lambda calculus is normally called the Church-Rosser theorem. The overall property is sometimes called the diamond property, as the diagram resembles a diamond (two routes branch out, but eventually come back together again). It also means that the final outcome of a "terminating" lambda expression will be identical no matter how you choose to apply beta-reduction.
However, not all lambda terms have one final outcome. This means the untyped calculus is not what we call normalising. There are plenty of lambda terms that will expand forever under beta-reduction (never reaching an irreducible, or normal form). In these situations, having some system for ordering your rewrites is useful, as it ensures that evaluation of programs proceeds identically for two identical programs.
Of course, you need to ensure you are respecting the binding rules of lambda, so you don't try and apply terms to the wrong lambda variables.
回答3:
This is obviously way after the question has been satisfactorily answered. However, I had to struggle a bit with the "order of evaluation" in lambda calculus and this more elaborate answer is mainly for posterity, in case someone else has the same doubts. The answer of @danyel was a great help, and I will be building on that.
As the OP rightly states, there is no explicit rule about the order of evaluation. However, the rule that applications are left-associative leads to such a rule - that the outermost application is to be evaluated before the inner ones.
In the expression,
(\kf.f(\c.co)km)(\x.dox)(\le.le)
:
let us first make some simplifications (using the first principles that each term e
is either a variable x
, an abstraction \x.y
, or an application e1e2
):
\c.co = e1
,\x.dox = e2
,\le.le = e3
.
This leads the original expression transforming to:
(\kf.f(e1)km)(e2)(e3)
.
Let us consider the leftmost term in the above expression:
(\kf.(f(e1)km)) = e4
and look closely at the body of the abstraction:
- (fe1)km
, or (f(\c.co))km
A beta redex (reducible expression) is an expression of the form (\x.e1)e2
. The above expression does not look like that and is not a beta redex (since based on the available info, f is not an abstraction). This is why it cannot be reduced and why it was wrong to apply \c.co
to k
.
So e4
is not reduced and kept as is, this leads to:
((e4)(e2))(e3)
.
((e4)(e2))
is the first beta redex, and indeed e2
replaces k
, as pointed out.
A further point, ((e4)(e2))
is not first applied to (e3)
for the same reason: it (((e4)(e2))e3
) is not a beta redex, it is of the form:
((\kf.body)e2)e3. The inner expression (\kf.body)e2) is the first valid beta redex that can be reduced. Doing this leads to the provided answer.
来源:https://stackoverflow.com/questions/14567313/beta-reduction-in-lambda-calculus-order-of-evaluation-important