为什么类型推断对面向对象语言不切实际?

时间:2014-03-20 09:26:20

标签: oop language-agnostic functional-programming type-inference static-typing

我目前正在研究一种新的编程语言的想法,理想情况下我希望这种语言能够混合一些功能和程序(面向对象)的概念。

我对Haskell等语言非常着迷的一点是,它是静态类型的,但你不需要注释类型(魔术感谢Hindley-Milner!)。

我真的很喜欢这种语言,但是在阅读了这个主题之后,似乎大多数人认为类型推断对于子类型/面向对象是不切实际/不可能的,但是我不明白为什么会这样。我不知道F#,但我知道它使用Hindley-Milner并且是面向对象的。

我真的想对此进行解释,最好是关于面向对象语言无法进行类型推断的场景的例子。

2 个答案:

答案 0 :(得分:11)

添加到seppk的响应:对于结构对象类型,他描述的问题实际上消失了(f可以给出多态类型,如∀A≤{x:Int,y:Int} .A→Int,甚至只是{x:Int,y:Int}→Int)。但是,类型推断仍然存在问题。

根本原因在于:在没有子类型的语言中,输入规则对类型强加相等约束。在类型检查期间处理这些非常好,因为通常可以使用类型的统一来立即简化它们。但是,通过子类型,这些约束被推广到不等式约束。你不能再使用统一,至少有三个不愉快的后果:

  1. 约束的数量和复杂性以组合方式爆炸。
  2. 如果出现错误,您必须向用户显示的信息是不可理解的。
  3. 某些形式的量化很快就会变得不可判断。
  4. 因此,对于子类型的类型推断并非不可能(90年代有很多关于这个主题的论文),但它并不是很实用。

    OCaml采用了一种更简单的替代方法,它使用所谓的行多态代替子类型。这实际上是易处理的。

答案 1 :(得分:5)

当使用名义输入(即一个打字系统,其成员具有相同名称和相同类型的两个类不可互换)时,会有许多可能的类型,如下所示:

let f(obj) =
    obj.x + obj.y

同时拥有成员x和成员y(支持+运算符的类型)的任何类都有资格成为obj的可能类型类型推断算法无法知道哪一个是你想要的那个。

在F#中,上面的代码需要一个类型注释。所以F#具有面向对象和类型推断,但不能同时进行(除了局部类型推断(let myVar = expressionWhoseTypeIKNow),它总是有效)。