Hindley-Milner推理可以为Go语言工作吗?


22

我读过Hindley-Milner不适用于具有子类的类型系统,并且还有其他类型系统功能也不能很好地使用它。Go当前在:=运算符中只有非常有限的类型推断。但是Go并没有传统意义上的子类,只有看起来与Haskell的类型类非常相似的接口,可以很好地与Hindley-Milner推理配合使用。

那么,Hindley-Milner推理在原理上是否可以像对Haskell一样进行推论?还是Go具有其他打破它的功能?(另一方面,Haskell还具有某些与Hindly-Milner不兼容的功能,如果要使用这些功能,则必须手动键入程序的那些部分。)

Answers:


35

Hindley-Milner类型推断用于Hindley-Milner类型系统,它是System-F类型系统的限制。HM类型系统的有趣特征是它们具有参数多态性(又名泛型)。那是Golang拒绝拥有的最大的单一类型系统功能。

在这种令人沮丧的限制下,HM风格的类型推断是不可能的。让我们看一下未键入的代码:

func f(a) {
  return a.method()
}

什么是f?我们可能会注意到a必须有一个方法,因此我们可以使用匿名接口:func f(a interface { method() ??? }) ???。但是,我们不知道返回类型是什么。使用类型变量,我们可以将类型声明为

func f[T](a interface{ method() T }) T

但是,Go没有类型变量,因此这行不通。虽然隐式接口使类型推断的某些方面更加容易,但现在我们无法找出函数调用的返回类型。HM系统要求声明所有函数,而不是暗含所有函数,每个名称只能具有一个类型(而Go的方法在不同的接口中可以具有不同的类型)。

相反,Go要求始终始终对函数进行完全声明,但允许变量使用类型推断。这是可能的,因为分配的右侧variable := expression在程序的那个位置已经具有已知的类型。这种类型推论是简单,正确和线性的。

  • 在声明时立即知道变量的类型,而HM推理必须首先潜在地对整个程序进行类型检查。这也对错误消息的质量产生了显着影响。
  • Go的类型推断方法将始终为变量选择最特定的类型,而HM选择最通用的类​​型。即使使用Go的隐式接口,这也可以清晰地处理子类型。

24
@bishop它是“合理的”,用于“理性”的极小的值。
hobbs

18
@bishop用通用语言完成编译器工作后,我当然可以同意:如果不使实现复杂化,很难实现。我甚至会用“不可能”代替“困难”。但是,这不是重点。关键是,是否值得增加额外的复杂性?对于使用或不使用泛型的任何人,答案显然都是“肯定的!” 我必须全心全意地同意这样的说法,即因为“哦,不,复杂性”是愚蠢的,所以拒绝实现泛型。
梅森惠勒

18
这也是Go开发人员假装各种FP不好的原因。围棋与词汇封一流的功能,并与能力创造更高阶的功能,但它不可能把它们什么好使用,因为该类型等基本功能mapfilter以及reduce都在Go的非常有限的不可言传类型系统。
hobbs

9
如果将其固定,@ hobbs和Go可能会是一种非常不错的语言,但是人们必须编写像gengen和这样的通用代库gonerics
cat

14
@cat这太可惜了。刚开始,Go似乎是一门充满创意的好语言,但是后来您意识到它没有继承性和多态性,因此您不能很好地进行OOP,并且它没有泛型,因此您也不能很好地完成FP,左眼呆呆地盯着屏幕问:“那你到底应该怎么用这种语言?!?”
梅森惠勒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.