【问题标题】:Why does (( (λf.λx.f(f(f(x)))) (λg.λy.g(g(y))) ) (λz.z + 1)) (0) evaluate to 8?为什么 (( (λf.λx.f(f(f(x)))) (λg.λy.g(g(y))) ) (λz.z + 1)) (0) 计算结果为 8?
【发布时间】:2021-06-08 02:15:45
【问题描述】:

所以我有这个 lambda 表达式:(λf.λx.f(f(f(x)))) (λg.λy.g(g(y)))(λz.z + 1)(0),我正在尝试手动评估它。他们的想法是(λf.λx.f(f(f(x)))) 基本上代表表达式f(f(f(x)))。然后同样(λg.λy.g(g(y))) 代表表达式g(g(y))。然后传入g(g(y)) 替换f。所以我们得到g(g(g(g(g(g(y))))))。或g 与自己组成6 次。然后我们将z+1 传递给g,然后将0 插入到最后的表达式中,最后得到6

>>>(((lambda f: lambda x: f(f(f(x))))(lambda g: lambda y: g(g(y))))(lambda z: z+1))(0)
8

问题是,当我使用 python 的内置 lambda 演算工具验证这个答案时,我得到 8 作为答案。

很明显,我的评估是错误的。我正在考虑将 2 g 组合物乘以 3 f 组合物得到 6。但显然我应该将其视为 2^3 组合物,但我不明白为什么。

【问题讨论】:

  • 顺便说一句,将 lambda 表达式转换为 Python 的出色工作。 lambda 演算有几个微妙之处,您似乎很了解语义,能够将其无缝转换为具体的编程语言。

标签: python lambda lambda-calculus


【解决方案1】:

你的直觉有点让你失望。尝试以“直观”的方式组合这两个表达式是很诱人的,但这样做会过度简化问题。让我们来看看前几个步骤。

这是您的 lambda 表达式,为了便于阅读,删除了一些无关的括号

(λf.λx.f(f(fx))) (λg.λy.g(gy)) (λz.z+1) 0

现在,您的直觉告诉您,我们通过让 f 成为 λy.g(gy) 来“组合”前两个函数。但事实并非如此。看,我们不会让f 成为λy.g(gy);我们让f 成为λg.λy.g(gy)(此时g 仍然是一个论点)。所以第一个简化适用于

(λx.(λg.λy.g(gy))((λg.λy.g(gy))((λg.λy.g(gy))x))) (λz.z+1) 0

这是一个令人困惑的混乱,但重点是被重复的位仍然有一个g 参数。然后我们为x 插入λz.z+1,这无疑是相当简单的

(λg.λy.g(gy)) ((λg.λy.g(gy))((λg.λy.g(gy))(λz.z+1))) 0

好的。现在在最里面的 redex 中,我们将让 g 成为 (λz.z+1)。因此,忽略该过程的几个步骤,我们将在y 上获得一个函数,它表示“将一个添加到这个东西两次”。即

(λg.λy.g(gy)) ((λg.λy.g(gy))(λy.y+2)) 0

好的,现在让我们再做一次。 redex 的左侧和以前一样,所以我们要在右侧做两次。右边的东西是“给这个数字加一”,所以我们得到

(λg.λy.g(gy)) (λy.y+4) 0

最后,做最后一次。我们将一个数字加四两次。

(λy.y+8) 0

对于大奖,零加八是......

8

【讨论】:

    【解决方案2】:

    像 Silvio 那样一步一步地走一遍绝对是一个很好的练习,但更简单:

    你将f->f^3应用于g->g^2,那不就是g->(((g^2)^2)^2) = g^8吗? 所以 (+1)^8 (0) = 8

    【讨论】:

    • 我明白了,我的直觉几乎是正确的,但有点错误。你能帮我尝试通过经典的 f(x) 形式来解释这一点吗?就像没有 lambda 表示法一样,我只是想理解这里的操作顺序,如果我能用正常的函数表示法理解它可能会有所帮助。就像我们说 f1(f,x)=(λf.λx.f(f(f(x)))) 然后 f1(f,x)=f(f(f(x))) 说 f2(g,y )=(λg.λy.g(g(y))) 然后 f2(g,y)=g(g(y)) 说 f3(z)=z+1 然后让 h1(g,x,y)= f1(f2(g,y),x)=g(g(y))(g(g(y))(g(g(y)))) 但是我不知道从这里去哪里。
    • 这样不行,你的符号 f1(f,x)=(λf.λx.f(f(f(x)))) 开始是错误的。它是 f1(f)=(λf.λx.f(f(f(x)))) 或 f1(f)(x)=f(f(f(x))),类似地 f2(g)=( λg.λy.g(g(y))) 或 f2(g)(y)=g(g(y))。 f2 在这里是“二阶”运算符(转换函数),而不是 2 个变量的函数),而 f1 是“三阶”运算符(转换作用于函数的一阶运算符)。如果您真的想带上 0 阶变量“x”,那么恐怕您必须像 Silvio 一样仔细完成所有步骤...
    • 也许这会让它更清楚?您可以使用外部运算符的 2 个变量的 lambda 重写您的 python 表达式:(lambda f, x: f(f(f(x))))(lambda g: lambda y: g(g(y)), lambda z: z+1)(0) 但我不知道如何为内部运算符做到这一点...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-04
    • 1970-01-01
    • 2019-05-08
    • 2020-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多