“向量连接的显式消去项完整写出依赖motive、空向量分支和带归纳结果的cons分支。独立核不信任“模式已覆盖”的标记,而重新检查生成的vecElim各前提;省去cons的错误后继分支在泛型声…”
形式陈述
Elaboration 区分便于书写的 surface language 与规则精小的 core theory。可把核心接口写成两种带输出的判断:
前者从表面项
应用规则可先综合
完备性只能相对于明确的 surface 设计陈述:某些声明式可定型项需要用户注解、显式 motive 或搜索提示;高阶 unification 与实例搜索一般没有同时终止且完备的算法。Elaboration 失败也不等于核心命题不可证,只说明当前信息流和搜索策略未找到项。
直觉
表面语言允许人省略显然信息,核心语言要求机器把每个依赖关系写清。Elaborator 就像排版前的技术编辑:根据上下文补上宇宙层、隐式类型参数和强制运输,把模式子句重排成核心消去;最后由独立内核检查成稿,而不是要求用户信任编辑过程没有猜错。
依赖类型让这种补全具有反馈回路。选择一个隐式实参会改变后续参数的类型,后续显式实参又可能反过来确定先前的 metavariable。双向方向标记限制信息流,约束队列保存尚未确定的部分;二者共同把全局猜测缩小成可管理的局部求解,却不能消灭固有歧义。
例子与边界
设核心恒等函数为
表面项 id true 没写隐式
若期望类型已经是
调用 append xs ys 会从两个向量的类型恢复
边界例子是 λx. x 处在 synthesis 位置且没有注解:
固定一个 Π/Nat/Vec 显式核心
前面的例子说明一般 elaboration 的信息流;现在单独固定核心
此处没有宇宙累积:
核心项只含变量、已检查常量、宇宙、Π、带参数类型的
自然数和向量的形成、构造规则为
消去子必须带齐 motive 和分支
自然数消去子是全参数项构造,规则为
向量的 motive 还必须接收向量自身,而不只是长度。给定
每行都是当前良构语境里的类型义务,不是 elaborator 可以宣称已解决的注释。尤其
消去子的四条 ι-计算为
若被消去项是变量等中立项,消去子停住,不凭长度猜出其所有元素。Nat/Vec 的这组显式接口与实现方式可对照文献。[1] 该教程用 Type:Type 简化实现;本页改用上面的分层规则,不借该简化版本声称正规化或一致性。
把向量连接编译成完整消去项
先把按第一个参数递归的加法声明为已检查的透明常量:
检查 motive 得到
对每个固定层级
在语境
完整定义为
消去结果是一个仍接受
- 基分支要求
。展开 motive 和add 0 n后得到 ,正由 居留。 - 后继分支里
。cons 的显式长度参数必须是 ,输出长度为其后继。期望的长度是 ,由加法计算转为同一后继,所以 conversion 成功。
这也解释了为什么按第一个向量消去时,选按第一个参数计算的加法最直接。把规格机械换成
独立核检查实际检查哪些东西
核心保存有限、有顺序的透明声明表
以下是全注解核心的检查接口。Sort(A) 综合 Check(t,A) 先确认 Conv(B,A)。综合规则逐个覆盖所有项构造:
| 核心项 | 必查前提与综合结果 |
|---|---|
| 变量/常量 | 查已检查语境/声明表,未知名字拒绝 |
| 输出 |
|
| 检查 |
|
| 综合 |
|
| Nat / zero / succ | 分别输出 |
| 检查 |
|
| 检查 |
|
| 检查 |
|
| 两种消去子 | 依前述规则检查所有类型参数、motive、分支和被消去项,再输出 |
Conv 只使用 λ 的 β、上述 ι 和已检查透明常量的 δ 展开,连同同余与 α 改名。不给函数 η、等式反映或任意数学定律开后门。一个直接实现把两侧递归归约到正规形,按绑定器的 α 等价比较。若得到同一个正规形,两条有限归约链就见证定义相等,conversion 有合法依据;层级标号也必须相同。
为了使这个教学检查器对任意输入都能返回,可给整个检查调用一个有限工作预算,每次递归处理语法节点和归约步骤都消耗预算;不足时返回 unknown,绝不返回 accept。这给出一个可能不完备的、终止的接受检查器,不需要把“所有原始语法都正规化”当成前提。更高效且完备的转换判定依赖相应类型理论的正规化、构造器可辨识性等元理论;正规化定理的输入首先是良构类型和良型项。[3]
接受可靠性按检查调用归纳即可定位每项责任:变量取已检查声明;Π 与 λ 使用良构扩张语境;应用由两个子推导和无捕获代入得到结果类型;Nat/Vec 构造与消去逐条使用上面的规则;conversion 成功时使用实际有限归约所见证的判断相等。声明表再按顺序归纳。因此每个接受结果都有核心推导,未知或拒绝都不产生可使用的声明。这是对所写算法的纸面论证;实际解析器、代入和归约实现仍在可信基中,不能称为已经机械化验证的软件。
两个向量的接受与两个错误候选
取
构造器规则分别综合 append xs ys 可以推断出这三个隐式参数;内核实际收到
依次应用 Π 消去,结果为
向量消去则先递归到空的左向量,返回
确有类型
若 elaborator 错把第一个长度填成 ih n ys、省去 cons,分支实际长度为
独立重检意味着内核不采用 elaborator 声称的长度、motive 正确性或“约束已解”标记,而是从显式项和已检查声明重新推导。若两个阶段共用同一个有缺陷的代入器,仍可能一起出错;阶段分离缩小信任范围,却不是形式验证的替代品。
推论与应用
Elaboration 把丰富语法与小可信内核分离。notation、type class、coercion、record projection 和 tactic 可以在不扩张核心证明规则的情况下加入,只要最终生成的项通过检查。这种架构还改善错误定位:约束记录了哪一个隐式选择导致类型冲突,编辑器可展示尚未解决洞的局部语境与目标。
分离也明确了信任边界。Elaborator 有 bug 时可能拒绝合法程序或生成错误项,但健全内核会拦下后者;若编译器绕过重检、让未解 metavariable 成为任意常量,可靠性便失效。性能优化如缓存规范形、增量约束求解和启发式实例搜索都必须保持最终 core judgment 不变。
参考资料
-
Ulf Norell, Towards a Practical Programming Language Based on Dependent Type Theory, PhD thesis, Chalmers University of Technology, 2007,metavariables、dependent pattern matching 与 Agda elaboration。
-
Jana Dunfield and Neel Krishnaswami, “Bidirectional Typing,” ACM Computing Surveys 54(5), 2021, Article 98,双向规则、注解与 elaboration 的可靠性/完备性框架。
-
The Agda Team, Agda User Manual, “Implicit Arguments,” “Metavariables,” and “Coverage Checking” sections,现代依赖语言的 surface-to-core 机制,accessed 2026。
-
[1] Andres Löh, Conor McBride, Wouter Swierstra, “A Tutorial Implementation of a Dependently Typed Lambda Calculus”, Fundamenta Informaticae 102(2), 2010, §§4.1–4.2:Nat/Vec消去子和显式连接;§5明确指出其
Type:Type简化的限制。 -
[2] Agda Team, Sort System,
univSort、funSort、piSort:层级后继与Π形成的最大值规则。本页只取固定自然数层级的片段。 -
[3] Carlo Angiuli and Daniel Gratzer, Principles of Dependent Type Theory,课程草稿,§§3.2.1–3.2.2:良构输入上的正规化接口与类型检查。此处有预算检查器的接受证明不等于引用该书得到一个现成实现正确性定理。