Lambda 微积分:捕获避免替换的递归定义
Lambda Calculus: Recursive definition of capture avoiding substitution
我花了几周时间编写了无类型 lambda 演算的实现。
我相信在这样做的过程中,我可能已经制定了一个递归定义来避免捕获替换(即它使用替换作为一种 alpha 转换形式),它非常适合维基百科上给出的替换定义。
如果有人能为我验证它的正确性,我将不胜感激,如果它是正确的,请解释为什么这个定义很少被使用,因为我发现它非常清晰和简单。
维基百科的定义:
x[x := N] ≡ N
y[x := N] ≡ y, if x ≠ y
(M1 M2)[x := N] ≡ (M1[x := N]) (M2[x := N])
(λx.M)[x := N] ≡ λx.M
(λy.M)[x := N] ≡ λy.(M[x := N]), if x ≠ y, provided y ∉ FV(N)
我的额外定义来强制避免捕获:
(λy.M)[x := N] ≡ λy'.(M'[x := N]), if x ≠ y and y ∈ FV(N)
其中
y' ∉ (FV(N) ∪ FV(M))
M' ≡ M[y:=y']
你的规则是正确的。
它不经常使用,因为它需要跟踪自由变量。这确实违反直觉,因为我们都同意名称无关紧要,而在此实现中,名称起着核心作用。
您还没有展示您的操作语义。如果这样做,您会看到应用程序规则需要知道 x
是否被 N
捕获,如 (λx.M) N
中那样。如果是这样,需要触发 alpha 重命名。
这里的问题是基本的一个表达式有太多(无限)表示。解决这个问题的一种典型方法是通过 de Bruijin 索引,或者称为本地无名的混合方法。
https://en.wikipedia.org/wiki/De_Bruijn_index
https://www.chargueraud.org/research/2009/ln/main.pdf
主要思想是相同的:两者都取绑定表达式的商,这样一个表达式恰好具有一种规范形式。
我花了几周时间编写了无类型 lambda 演算的实现。
我相信在这样做的过程中,我可能已经制定了一个递归定义来避免捕获替换(即它使用替换作为一种 alpha 转换形式),它非常适合维基百科上给出的替换定义。
如果有人能为我验证它的正确性,我将不胜感激,如果它是正确的,请解释为什么这个定义很少被使用,因为我发现它非常清晰和简单。
维基百科的定义:
x[x := N] ≡ N
y[x := N] ≡ y, if x ≠ y
(M1 M2)[x := N] ≡ (M1[x := N]) (M2[x := N])
(λx.M)[x := N] ≡ λx.M
(λy.M)[x := N] ≡ λy.(M[x := N]), if x ≠ y, provided y ∉ FV(N)
我的额外定义来强制避免捕获:
(λy.M)[x := N] ≡ λy'.(M'[x := N]), if x ≠ y and y ∈ FV(N)
其中
y' ∉ (FV(N) ∪ FV(M))
M' ≡ M[y:=y']
你的规则是正确的。
它不经常使用,因为它需要跟踪自由变量。这确实违反直觉,因为我们都同意名称无关紧要,而在此实现中,名称起着核心作用。
您还没有展示您的操作语义。如果这样做,您会看到应用程序规则需要知道 x
是否被 N
捕获,如 (λx.M) N
中那样。如果是这样,需要触发 alpha 重命名。
这里的问题是基本的一个表达式有太多(无限)表示。解决这个问题的一种典型方法是通过 de Bruijin 索引,或者称为本地无名的混合方法。
https://en.wikipedia.org/wiki/De_Bruijn_index
https://www.chargueraud.org/research/2009/ln/main.pdf
主要思想是相同的:两者都取绑定表达式的商,这样一个表达式恰好具有一种规范形式。