[编辑:Voilà每句话几句话]
有几种扩展HM类型推断的方法。我的回答是基于许多成功或多或少成功的尝试来实现的。我偶然发现的第一个参数多态性。试图在此方向上扩展HM的类型系统倾向于系统F,因此需要类型注释。我遇到的这个方向的两个值得注意的扩展是:
HMF,它允许对所有System-F类型进行类型推断,这意味着您可以在类型的“中间”进行通用量化,其外观不像HM多态类型那样隐式地位于最高范围内。该文件明确指出,关于可能需要多少个类型注释以及在何处需要类型注释,没有明确的规则。同样,类型是系统F的类型,术语通常没有主体类型。
MLF不仅是HM的扩展,还是System F的扩展,它通过引入一种对类型的有界量化来重新获得HM的主类型属性。作者进行了比较,MLF严格比HMF强大,并且注释仅对于多态使用的参数是必需的。
扩展HM的另一种方法是通过更改约束域。
HM(X)是在约束域X上参数化的Hindley-Milner。在这种方法中,HM算法生成发送到X的域求解器的约束。对于通常的HM,域求解器是统一过程,并且域由根据类型和类型变量构建一组术语。
X的另一个示例可以是用Presburger算术语言(这种情况下类型推断/检查是可确定的)或Peano算术语言(不再可确定)表达的约束。X沿各种理论变化,每种理论对类型注释的数量和位置都有自己的要求,范围从根本到全部。
Haskell的类型类也是约束域的一种扩展,它通过添加形式的类型谓词MyClass(MyType)
(这意味着存在MyType类型的实例MyClass)。
类型类保留类型推断,因为它们基本上是(几乎)正交的概念,它们实现了即席多态性。
举个例子,拿一个可以有实例val
的类型符号,等等。在代码中引用该符号时,实际上是因为已经执行了类型推断,编译器才可以推断要使用哪个类实例。这意味着,依赖的类型取决于使用它的上下文。这就是为什么运行单个语句会导致val :: MyClass a => a
MyClass A
MyClass B
val
val
ambiguous type error
:编译器无法根据上下文推断任何类型。
对于更高级的类型系统,如GADT,类型族,从属类型,系统(F)ω等,类型不再是“类型”,它们成为复杂的计算对象。例如,这意味着看起来不同的两种类型不一定是不同的。因此,类型相等性变得不平凡。
为了给您一个实际复杂度的例子,让我们考虑list的依赖类型:NList a n
where a
是列表中对象的类型,n
它是长度。
append函数的类型为append :: NList a n -> NList a m -> NList a (n + m)
,而zip函数的类型为zip :: NList a n -> NList b n -> NList (a, b) n
。
想象现在我们有了lambda \a: NList t n, b: NList t m -> zip (append a b) (append b a)
。这里zip的第一个参数是type NList t (n + m)
,第二个参数是type NList t (m + n)
。
几乎相同,但是除非类型检查器知道“ +”在自然数上换位,否则它必须拒绝该函数,因为(n + m)并非字面意义(m + n)。它不再与类型推断/类型检查有关,而与定理证明有关。
液体类型似乎在进行一些从属类型推断。但是据我了解,它并不是真正的依赖类型,更像是普通的HM类型,可以对其进行额外推断以计算静态范围。
我希望这有帮助。