TAPL04 Typed Lambda
Published:
Simply Typed Lambda Calculus 通常记为 $\lambda_{\rightarrow}$
Intro
在 ULC + Bool + Nat 中会出现某个项 $T$ 卡住的情况,意思是
- $T$ 不是值,且
- 不存在 $T’\neq T$ 使得 $T\rightarrow T’$
例如经典的 suc True 就没法推导
解决方案是静态地给项加上类型,在运行前做类型检查,然后证明所有通过类型检查的项都终会推导成值
一个比较有意思的点是,我们可以将每个项都视为一种类型,这时候做类型检查(类型推导)就完全等价于对项本身进行推导。并且由于 LC 是图灵完备的(例如经典的 $\Omega$),这样的类型推导可能不终止。
这说明所有有用的类型推导(停机的类型推导)必将做出过近似。意思是存在一个不会卡住(well-behaved)的项 $T_w$,$T_w$ 没法通过类型检查。
还可以回想静态分析做的事情(也是在静态时过近似,用各种 derivation rules 做约束求解),所以说这玩意是同属于 PL 下的细分分支。甚至对于指针分析,只需要把对象集看成类型,那么求解过程本质上就是在定 type 了。
Definition
Types
定义类型集合 $\scr T$ 为满足如下约束的最小集
- $\text{Bool}\in {\scr T}$
- $\forall A,B\in {\scr T}, A\rightarrow B\in{\scr T}$
②实际上是引入了产生复杂类型的方法,称 $\rightarrow$ 为类型构造子。例如我们可以有 $\newcommand{tBool}{\text{Bool}} (\tBool\rightarrow\tBool)\rightarrow\tBool$ 这样的类型
Typing relation
我们把 $M: \tau$ 称为 typing judgement。又因为这实际上是 $T, {\scr T}$ 上的二元关系,因此也叫 typing relation。
对于这样的二元关系也存在推导(derivation rules),通常写成 $\dfrac{\text{premise}}{M:\tau}$ 这样的形式。
很显然并非所有的项都可以推导出一个类型(例如经典的 $\Omega$),因此做关于类型的表述时通常说 “若项 $M$ 存在类型 $\tau$” 这样的句子。
$\lambda$-abstractions
给出了类型集合的定义后,需要考虑的就是如何给项标记类型(怎么做 structural 的类型推导)。关键的地方在于形如 $\lambda x.\; M$ 的项要如何确定类型。
这里插几句。由于前面提到的 $\tBool$-calculus 是没有变量的,所有的符号都是常元,因此所有的类型都可以通过 structural 的过程得出。
在这里因为引入了 $\lambda$-abstraction,所以会出现变量(回忆函数内访问参数)。如何推导函数的类型,本质上就是如何推导函数参数和返回值的类型。
- explicitly typed: 可以手动给参数加上类型注解,然后推导返回值的类型
- implicitly typed: 可以约束求解,此时得到的参数类型是一个可能类型的集合
①很好理解,②可以类比 haskell 里面无类型注解的函数会用 typeclass 来限制参数的类型,这是一种从 body 到参数的类型推导
为了简单,书选择了把项写成 $\lambda x:\tau. M$ 的形式
Typing context
同时因为 $\lambda$-abstraction 的出现,项 $T$ 中可能存在自由变元。这时候的 $T$ 的类型在这些自由变元取不同类型时可能有不同的类型,因此引入typing context $\Gamma$。
$\Gamma$ 为 typing judgement 的集合,类似命题逻辑有 $\Gamma\vdash M:\tau$ 这样的记号,含义为“在假设 $\Gamma$ 成立时,$M$ 类型为 $\tau$”
Derivation rules
这个形式和命题逻辑的推理系统 G’ 具有形式上的一致性,非常漂亮的一个结论。当然也可以认为做类型推导本身就是在构造一个逻辑系统,反过来命题逻辑恰好足够表达 STLC 的类型推导。 \(\frac{}{\Gamma,x:\tau\vdash x:\tau}\)
\[\dfrac{\Gamma,x:\tau\vdash M:\sigma}{\Gamma\vdash\lambda x:\tau.\; M:\tau\rightarrow\sigma}\] \[\frac{\Gamma\vdash M:\tau\rightarrow \sigma\quad \Gamma\vdash N:\tau}{\Gamma\vdash M\; N:\sigma}\]Meta Theorems
证明都是简单的,熟练掌握归纳法就可以了
Uniqueness of types
若 $M:\tau$,则 $\forall \sigma\in{\scr T}$,$M:\sigma\Rightarrow \tau=\sigma$
只需要证明 derivation tree 到项存在双射即可。
Progress
若 $\vdash M:\tau$,则
- 要么 $M$ 为值
- 要么 $\exists M’\neq M$ 使得 $M\rightarrow M’$
说的是我们的类型系统可以保证所有通过类型检查的项不会卡住
Preservation
几个比较显然的引理:
- 若 $\Gamma\vdash M:\tau$,则 $\Gamma,x:\sigma\vdash M:\tau$
- 若 $\Gamma\vdash M:\tau$,则 $\Delta\vdash M:\tau$,其中 $\Delta$ 为 $\Gamma$ 的任意重排
- 若 $\Gamma,x:\tau\vdash M:\sigma$ 且 $\Gamma\vdash N:\tau$,则 $\Gamma\vdash M[N/x]:\sigma$。证明只需要对 $M$ 结构归纳即可。
若 $\Gamma\vdash M:\tau$,且 $M\rightarrow M’$,则 $\Gamma\vdash M’:\tau$
同样只需要对 $M$结构归纳即可。
Erasure Property
定义类型擦除函数 $\text{erase}(\cdot)$。Erasure Property 说的是 $\text{erase}$ 函数建立了 $\lambda_\rightarrow$ 到 $\lambda$ 的同态(很显然不是双射)。或者你也可以说成是 $\text{erase}$ 函数与 $\rightarrow$ 是可交换的(虽然这里的两个箭头是各自项集上的二元关系)。
通常把这个 erasure 也叫抽象的 compilation,这时候就说的是无类型的 low-level(汇编层面)语义和原语言等价。
