| 维度 | 分类 | 说明 |
|---|
| 类型检查时机 | 静态/动态 | 编译时/运行时 |
| 类型转换 | 强/弱 | 隐式转换的严格程度 |
| 类型推断 | 显式/隐式 | 是否需要声明类型 |
Hindley-Milner 类型推断:
自动推断表达式的最一般类型:
算法W(Γ,e)=(S,τ)
其中 Γ 为类型环境,S 为替换,τ 为类型。
多态类型:
id:∀α.α→α
Let 多态:
let id = λx.x in (id 1, id true) -- 合法
而:
(λid.(id 1, id true))(λx.x) -- 不合法(ML中)
子类型关系 S<:T 表示 S 类型的值可以用在期望 T 类型的地方。
函数子类型的协变与逆变:
- 参数类型:逆变(contravariant)
- 返回类型:协变(covariant)
S1→S2<:T1→T2⟺T1<:S1∧S2<:T2
Liskov 替换原则(LSP):
若 S<:T,则 T 类型的对象可被 S 类型的对象替换,程序行为不变。
积类型(Product):
A×B={(a,b)∣a∈A,b∈B}
和类型(Sum):
A+B=inl(a)∣inr(b)
类型同构:
| 类型表达式 | 等价于 |
|---|
| A×1 | A |
| A+0 | A |
| A×B | B×A |
| A+B | B+A |
| AB+C | AB×AC |
| (A×B)C | AC×BC |
语法:
e::=x∣λx.e∣e1 e2
β 归约:
(λx.e1) e2→e1[x:=e2]
α 转换:
λx.e≡αλy.e[x:=y]
η 归约:
λx.(f x)→ηf(x∈/FV(f))
| 策略 | 说明 | 特点 |
|---|
| 正则序 | 最左最外先归约 | 可能重复计算 |
| 应用序 | 最左最内先归约 | 可能不终止 |
| 惰性求值 | 仅在需要时归约 | 避免不必要计算 |
| 急切求值 | 参数先求值 | 实用 |
Church 布尔值:
true=λt.λf.t
false=λt.λf.f
Church 数:
0=λf.λx.x
1=λf.λx.f x
2=λf.λx.f (f x)
n=λf.λx.fn x
后继:
succ=λn.λf.λx.f (n f x)
加法:
plus=λm.λn.λf.λx.m f (n f x)
实现不动点,允许递归:
Y=λf.(λx.f (x x)) (λx.f (x x))
Y f=f (Y f)
类型语法:
τ::=B∣τ1→τ2
类型规则:
Γ⊢x:τx:τ∈Γ (Var)
Γ⊢λx:τ1.e:τ1→τ2Γ,x:τ1⊢e:τ2 (Abs)
Γ⊢e1 e2:τ2Γ⊢e1:τ1→τ2Γ⊢e2:τ1 (App)
类型安全 = 进展性 + 保持性:
- 进展性:良类型的闭项要么是值,要么可以归约
- 保持性:归约保持类型不变
定义单步归约关系 →:
e1 e2→e1′ e2e1→e1′
e2→e2′v1 e2→v1 e2′
(λx.e) v→e[x:=v]
定义求值关系 ⇓:
e1 e2⇓ve1⇓λx.ee2⇓v2e[x:=v2]⇓v
| 特性 | 小步语义 | 大步语义 |
|---|
| 粒度 | 单步归约 | 直接到结果 |
| 非终止 | 可描述 | 无法描述 |
| 并发 | 适合 | 不适合 |
| 证明 | 归纳简单 | 可能更直观 |
将程序映射到数学对象(域论中的元素):
[[e]]:Env→Value
[[x]]ρ=ρ(x)
[[λx.e]]ρ=λv.[[e]]ρ[x↦v]
[[e1 e2]]ρ=([[e1]]ρ)([[e2]]ρ)
递归定义的语义通过域论中的最小不动点给出:
[[fix]]=lfp(F)=⨆n=0∞Fn(⊥)
Hoare 三元组:
{P} C {Q}
含义:若前置条件 P 成立,执行命令 C 后,后置条件 Q 成立。
推理规则:
{P} skip {P}
{Q[x:=e]} x:=e {Q}
{P} C1;C2 {Q}{P} C1 {R}{R} C2 {Q}
{P} if b then C1 else C2 {Q}{P∧b} C1 {Q}{P∧¬b} C2 {Q}
{P} while b do C {P∧¬b}{P∧b} C {P}
循环不变式 I 必须满足:
- 初始化:循环开始前 I 成立
- 保持:每次迭代后 I 仍然成立
- 终止:循环结束时 I∧¬b 可推出 Q
wp(x:=e,Q)=Q[x:=e]
wp(C1;C2,Q)=wp(C1,wp(C2,Q))
wp(if b then C1 else C2,Q)=(b⇒wp(C1,Q))∧(¬b⇒wp(C2,Q))
类型系统是一种轻量级程序验证:
| 验证级别 | 方法 | 保证 |
|---|
| 类型检查 | 编译器 | 类型安全 |
| 静态分析 | 分析工具 | 特定属性 |
| 程序证明 | 证明助手 | 完全正确性 |
依赖类型:类型可以依赖于值,允许在类型层面表达更精细的属性。
Vec(A,n):Type
长度为 n 的 A 类型向量,类型检查器可验证列表操作的正确性。