Skip to content

定义Definition

局部无名表示

Locally nameless representation · 局部无名称表示

用索引表示绑定变量、用原子表示自由变量,以局部闭合与开启关闭条件检查绑定操作的合法性。

形式陈述 ​

自由名字与绑定距离分开存 ​

局部无名表示使用两种不同的变量构造:bvar(i) 是de Bruijn 索引,fvar(a) 是自由原子。语法为

t::=bvar(i)∣fvar(a)∣λ.t∣tt.

原子来自可判等、总能选出新名字的无限集合。λx.xz 表示为 λ.(bvar(0)fvar(z))。绑定器仍无名,故 α 改名不改变表示;自由 z 不依赖外部名字表中的编号。[1, §§2.4–3.1]

原始语法允许无效项,所以要定义“在深度 k 局部闭合”谓词 lck:自由原子总合法,bvar(i) 要求 0≤i<k,进入 λ 时检查 lck+1,应用两边都要通过。完整项合法是 lc0(t)。这不要求没有自由原子,而是要求没有悬空的绑定索引;fvar(z) 合法,孤立的 bvar(0) 不合法。

开启与关闭 ​

开启 openk(t,u) 将索引恰好为 k 的绑定变量替成 u,其他变量不变;进入 λ 后把 k 加一,应用分别递归。写 open(t,u)=open0(t,u)。本文的安全接口要求 lc1(t) 且 lc0(u):t 是一个合法 λ 的函数体,u 是完整合法项。

关闭 closek(t,a) 将所有自由原子 a 换成 bvar(k),其他原子与原有绑定索引保持不变;进入 λ 时同样增加 k。简写 close(t,a)=close0(t,a)。若 t 局部闭合,则 λ.close(t,a) 也是局部闭合的项。

设 FV(t) 是 t 中自由原子的集合,则两条可实际检验的逆律是

open(close(t,a),fvar(a))=t若 lc0(t),close(open(b,fvar(a)),a)=b若 lc1(b), a∉FV(b).

第一式原本所有 a 都属于被关闭的自由原子;第二式必须防止原有自由 a 混进新开的形参。开启的结构操作本身能在更多原始项上运行,本文给出的是具有绑定解释的接口,而不是把函数“能算出某个树”当成作用域保证。[1, §§3.1–3.4]

直觉

为什么这里不用提升实参 ​

合法实参 u 中的索引都已由 u 自己的 λ 绑定;u 的外部引用全部是自由原子。把整个 u 放到另一个 λ 下面,其内部索引仍由原来的内部 λ 负责,自由原子又不会被无名 λ 绑定。因此开启可以直接放入 u,不必改变任何数字。

这依赖 lc0(u)。把有悬空 bvar(0) 的原始项当作 u 塞进一个 λ,0 会突然指向那个 λ;“局部无名不需要提升”不能脱离合法实参条件使用。若处理多个尚未打开的外层绑定器,需要更一般的操作或先把外层开启成新鲜原子,不能直接套本文单绑定器接口。

例子与边界

同一无捕获收缩,两种表示 ​

对 (λx.λy.x)z,表示为

(λ.λ.bvar(1))fvar(z).

开启外层函数体 b=λ.bvar(1) 时,进入内层 λ 后目标索引由 0 变成 1,于是得到 λ.fvar(z)。没有先后提升,但仍然准确数过了绑定器。最后一项是常返回自由 z 的函数,不是恒等函数 λ.bvar(0)。

不新鲜的关闭会合并两种来源 ​

令 b=bvar(0)fvar(z)。用新鲜 a 开启,得到 fvar(a)fvar(z);再关闭 a,正好恢复 b。若改用已有自由原子 z 开启,则得到 fvar(z)fvar(z),关闭 z 后变成 bvar(0)bvar(0)。第二个 z 原本自由,现在也被绑定了,所以第二条逆律的 freshness 条件不可省。

局部闭合的反例是 λ.bvar(1):内部深度只有 1,合法索引只能是 0。另一方面 λ.fvar(z) 虽含自由名,却局部闭合。把“局部闭合”翻译成“整个程序没有自由变量”,会错误排除后者并破坏开启操作的接口。

自由原子的替换 ​

将自由 a 替换为局部闭合 u 时,只改 fvar(a);遇到 λ 无须改名或提升,继续递归即可。以 λ.(bvar(0)fvar(a)) 为例,代入 u=λ.bvar(0) 得 λ.(bvar(0)(λ.bvar(0)))。两处 0 分别由各自最近的 λ 绑定,没有互相干扰。

推论与应用

逆律怎样证明,怎样用于绑定证明 ​

按树结构同时跟踪当前深度。自由原子分支直接判等;绑定索引分支检查是否等于当前开启深度;λ 分支将深度加一后使用归纳假设。第一条逆律中局部闭合保证原来没有“恰好指向将被新建的外层 λ”的悬空索引;第二条中 freshness 保证关闭时只找回刚开启的原子,而不误收旧的自由出现。这给出逆律条件的实际作用,不只是把条件列在公式旁。

在带绑定的归纳证明中,可以先选不在一个有限禁用集里的原子 a,把函数体开启成普通自由变量,再对开启项推理。文献还使用“除有限集合外所有 a”的余有限量化,使归纳假设能选择适合后续上下文的新鲜原子;这种组织方式让归纳假设有足够的新鲜名字可选,具体使用时仍须给出有限禁用集。[1, §4.2]

开启与关闭各遍历函数体一次。不可变树共享被放入的 u 时,开启有 B 个体节点的工作为 O(B);若必须完整复制每处实参,含 q 个目标出现、实参大小 S 的结果需 O(B+qS) 空间与构造时间。表示上的无提升减少了某类重编号工作,并不消除替换造成的结果增长。

迁移练习:把上例已有自由原子 z 改成 a,再尝试“总使用名字 a 开启”的实现。写出失败树,并改成从 FV(b) 以外选择原子。然后把实参换成悬空 bvar(0),检查接口应先拒绝,而非生成一个看似可用的捕获结果。终点任务提供两种逆律与非法参数的复算。

参考资料

[1] Arthur Charguéraud,The Locally Nameless Representation,作者稿 §§2.4、3.1–3.6:双变量语法、开启关闭、局部闭合、自由替换与一般项开启;§4.2:余有限量化。正式版 Journal of Automated Reasoning 49,2012,363–408,DOI 10.1007/s10817-011-9225-2;作者页面列在线发表时间 2011。

[2] Brian Aydemir、Arthur Charguéraud、Benjamin C. Pierce、Randy Pollack、Stephanie Weirich,Engineering Formal Metatheory,POPL 2008,§3:局部无名表示及绑定操作的前提。本文只采用单绑定器、局部闭合实参的接口。

关系图谱3 个相邻概念 · 1 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组