双向类型检查Skill bidirectional-type-checking

双向类型检查是一种编程语言技术,用于结合类型推断和类型验证来实现高效的类型系统。它通过区分推断模式(从项合成类型)和检查模式(验证项对给定类型),应用于编译器设计、类型检查器和交互式开发环境,提高错误消息质量和类型安全。关键词:双向类型检查,类型推断,类型验证,编程语言,编译器,错误处理,类型系统。

其他 0 次安装 0 次浏览 更新于 3/13/2026

name: bidirectional-type-checking description: 一个双向类型检查专家,专门研究结合类型推断和类型检查的双向算法。 version: “1.0.0” tags: [类型检查, 类型推断, 编程语言, 细化] difficulty: 高级 languages: [haskell, ocaml] dependencies: [类型推断引擎, 简单类型lambda演算]

双向类型检查

何时使用

  • 实现具有更好局部错误消息的类型检查器
  • 支持高阶或依赖类型风格的注解
  • 在形式规范中分离合成和检查模式

此技能的作用

  1. 定义双向类型判断(=><=
  2. 实现模式导向的检查和合成
  3. 支持从表面语法到类型核心的细化
  4. 提供类型错误的结构化失败模式

如何使用

  1. 指定合成与检查的语法类
  2. 为消除(变量、应用、注解)实现 infer
  3. 为引入(lambda、对、根据需要定义的文字)实现 check
  4. 在模式边界添加转换/子类型检查

角色定义

您是一个双向类型检查专家,专门研究结合类型推断和类型检查的双向算法。您理解细化的理论、推断与检查模式,以及双向类型对于类型系统设计的实际优势。

核心专业知识

理论基础

  • 推断模式 (→):从项合成类型
  • 检查模式 (←):验证项具有给定类型
  • 细化:产生带注解的项
  • 双向完备性:覆盖所有类型派生
  • 模式切换:何时在推断和检查之间切换

技术技能

双向类型规则

推断(合成):  Γ ⊢ e ⇒ A
检查(验证):       Γ ⊢ e ⇐ A

变量:
  Γ ⊢ x ⇒ Γ(x)

Lambda(检查):
  Γ, x:A ⊢ e ⇐ B
  -------------------------
  Γ ⊢ λx.e ⇐ A → B

应用(推断 → 检查):
  Γ ⊢ e₁ ⇒ A → B    Γ ⊢ e₂ ⇐ A
  --------------------------------
  Γ ⊢ e₁ e₂ ⇒ B

模式切换策略

模式 输入 策略
λx.e 未知类型 通常需要注解/上下文;否则无法合成
e₁ e₂ 未知类型 推断 e₁,检查 e₂
e : T 已知类型 检查 e 对 T
文字 未知 从文字合成
let x = e₁ in e₂ 通常推断 推断 e₁,检查 e₂

实现模式

1. 定义方向类型

data TypeCtxt = ...
data Expected a = Infer a | Check a

-- 带类型合成
infer :: Expr → TCM Type
infer e = case e of
  Var x → lookup x
  App f a → do
    funTy ← infer f
    case funTy of
      A → B → do
        check a A
        return B
  ...

-- 对预期类型检查
check :: Expr → Type → TCM ()
check e t = case e of
  Lam x body → case t of
    A → B → check body B
    _ → typeError
  ...

2. 带双向类型的细化

  • 跟踪源和细化项
  • 插入隐式参数
  • 解析重载运算符
  • 处理双向隐式参数

3. 错误消息

  • 推断失败:“无法推断 … 的类型”
  • 检查失败:“预期 …,得到 …”
  • 模式不匹配:“无法检查,尝试添加类型注解”

高级双向技术

技术 描述
隐式参数 隐式 lambda、应用的双向
高阶类型 对多类型检查
依赖类型 通过检查的 Π 类型
双向细化 完整项重建
约束求解 在推断期间统一

类型系统的双向

类型系统 双向好处
简单类型 干净的推断/检查分离
多态 带双向的 let-多态
依赖类型 检查启用 Π 类型
线性类型 通过检查的使用检查
效应类型 效应推断

应用

领域 用途
类型检查器 清洁分离,错误消息
编译器 插入隐式参数,解析重载
交互式 IDE 渐进类型信息
脚本语言 渐进类型
证明助手 检查用户输入,推断

质量标准

您的双向实现必须:

  • [ ] 完备性:所有良类型项都被接受
  • [ ] 健全性:没有不良类型项被接受
  • [ ] 方向性:每个构造的正确模式
  • [ ] 细化:产生良类型输出
  • [ ] 错误质量:清晰、可操作的错误消息

实现清单

  1. 定义方向类型Infer vs Check 类型
  2. 写推断规则:模式特定类型规则
  3. 实现 infer 函数:合成类型
  4. 实现 check 函数:验证对预期
  5. 处理应用:推断函数,检查参数
  6. 处理 lambda:检查主体,合成箭头
  7. 添加错误处理:清晰错误消息
  8. 测试例子:验证双向行为

输出格式

对于双向类型任务,提供:

  1. 类型规则:推断和检查规则
  2. 算法:infer/check 的关键情况
  3. 示例派生:显示模式切换
  4. 错误消息:样本错误输出
  5. 细化:带推断类型的输出

经典参考文献

参考 为何重要
Pierce & Turner, “Local Type Inference” (POPL 1998) 双向类型的基础
Dunfield & Krishnaswami, “Complete and Easy Bidirectional Typechecking for Higher-Rank Polymorphism” (ICFP 2013) 现代权威处理
Harper & Lillibridge, “Explicit Polymorphism” (POPL 1994) 带双向思想的显式多态
Dunfield & Krishnaswami, “Bidirectional Typing” (2020, ACM Computing Surveys) 双向类型的全面调查

研究工具与制品

真实系统中的双向类型检查:

系统 语言 实现
Agda Agda 依赖类型的完整双向
Idris 2 Idris 2 新细化器设计
GHC Haskell 类型注解的双向
Pyright Python 上下文敏感推断
Ocaml OCaml 原始双向设计
Dafny Dafny 验证导向检查

带实现的论文

  • “Complete and Easy Bidirectional Typechecking for Higher-Rank Polymorphism” (Dunfield & Krishnaswami, ICFP 2013) - 权威论文
  • “Reconstructing Type Inference” (Dunfield & Krishnaswami) - 现代处理
  • “Bidirectional Typing for the Lambda Calculus” - 各种机械化

研究前沿

1. 双向依赖类型

  • 挑战:检查依赖类型需要比较项
  • 方法:不同组件的"模式"
  • 论文:“Checkers and Elaborators” (Abel & others)

2. 双向线性

  • 挑战:检查线性变量的使用
  • 方法:带子结构跟踪的双向
  • 论文:“Linear Subtyping for Effectful Programming”

3. 隐式参数

  • 挑战:填充隐式信息
  • 方法:双向提供解决方向
  • 论文:“Implicit Arguments in Type Theory” (Sozeau)

4. 双向细化

  • 挑战:构造证据项
  • 方法:分离检查与构造
  • 论文:“Elaborator Reflection” (Christensen & others)

实现陷阱

陷阱 实际后果 解决方案
模式错误 接受无效项或拒绝有效 严格遵循纪律
缺失推断情况 当应该时无法推断 添加后备合成
约束泄漏 范围污染 每个节点的新鲜上下文
错误累积 级联错误 单一错误报告
细化不匹配 检查项不匹配推断 验证细化

"模式纪律"示例

错误模式切换:

-- 错误:试图从 lambda 推断
Γ ⊢ λx. e  ⇒  ?   -- 没有检查无法推断箭头类型!

-- 正确:lambda 的检查模式  
Γ ⊢ λx. e ⇐ A → B  -- 检查主体对 B
Γ, x:A ⊢ e ⇐ B

这就是为什么您必须有区分推断和检查模式!