“现代编译器常使用更丰富的System Fω、带类型类或显式强制的核心。Fω不仅让项对普通类型量化,还让类型算子接收类型参数并进行β计算;先用kind判断区分List与List Int,才能检…”
形式陈述
System Fω在System F的显式类型多态上加入高阶类型算子。它的“高阶”首先发生在类型层:类型函数可以接收另一个类型函数,项也能对这种类型函数量化。
固定Church-style核心,即项参数类型、类型抽象的kind和类型应用都明确写出。类型表达式为
例子另加Int、Bool及积类型,它们只是标准的基础类型扩展。kind环境Δ按类型算子规则检查类型,且
注意两个绑定子的区别:
项语法仍包含
还须允许类型级β计算:
本页固定
直觉
System F能够写“对任何元素类型A都可用”的函数。Fω还可以写“对任何容器形状F都可用”的接口。区别不是把类型变量名字换成大写,而是F本身具有输入kind:F A才是完整类型。
同时,类型表达式现在会计算。PairWith Int Bool可以先展开一个类型函数,化成Int×Bool,再与二元组值的类型比较。项级检查器必须知道这些不同写法何时表示同一个类型。
例子与边界
先检查类型算子,再检查项
定义
它的kind为
在F、A的假设下,F A具有kind
检查应用
第一步,PairWith Int的kind是
值 (7,true)恰有这个类型。因此整个应用类型为Int×Bool,求值结果还是 (7,true)。没有在运行时对Int或Bool作分支;类型应用只告诉检查器这次使用什么实例。
若把第一次参数改成Int,kind检查立即拒绝,因为 (7,8),kind全部合法,但项级类型不匹配:Int×Int不是Int×Bool。这两个错误属于不同层。
高kind不自动提供容器操作
映射操作可以有如下接口:
这个类型是kind正确的,却不意味着任意F都自带满足容器规律的map。例如固定
Kind只说明F怎样接收类型参数,不提供运行时映射操作,更不提供它保持恒等与复合的证据。若要写容器通用算法,通常把已经实现的map作为额外参数传入,并根据需要另声明或证明相应规律。
同样,两个算子都有kind
与依赖类型、隐式推断的边界
Fω不让类型读取任意运行时项。
本页的项是显式标注的。删除所有类型抽象、应用和注解后,重新恢复它们是另一个问题,不能从“显式类型检查可判定”推出“隐式推断只需扩展Algorithm W”。
推论与应用
显式检查的关键步骤是类型相等判定。类型层可视为带构造器的简单kind λ演算;良kind类型计算的正规化与类型级β的合流性给出可比的β正规形。检查器先验证kind,再将需要比较的类型正规化并作α等价比较;因此本页固定核心的检查会终止。正规化可能制造很大的中间类型,终止不等于具有小的多项式成本。
类型保持证明中多了一个重要引理:若
Fω适合表达高kind库接口和显式多态编译核心。它把“接口需要什么类型构造器”“程序需要什么运行时操作”“哪些类型写法可通过计算互换”分成三个可检查问题,使后续加入字典或其他证据时有清晰边界。
参考资料
- Andrew M. Pitts, Lecture Notes on Types, 2015,§5.3:Fω、类型构造器量化与高阶接口
- Benjamin C. Pierce, Types and Programming Languages, MIT Press, 2002,Chapters 29–30:类型算子、类型等价与Fω