我目前正在研究一种新的编程语言的想法,理想情况下我希望这种语言能够混合一些功能和程序(面向对象)的概念。
我对Haskell等语言非常着迷的一点是,它是静态类型的,但你不需要注释类型(魔术感谢Hindley-Milner!)。
我真的很喜欢这种语言,但是在阅读了这个主题之后,似乎大多数人认为类型推断对于子类型/面向对象是不切实际/不可能的,但是我不明白为什么会这样。我不知道F#,但我知道它使用Hindley-Milner并且是面向对象的。
我真的想对此进行解释,最好是关于面向对象语言无法进行类型推断的场景的例子。
答案 0 :(得分:11)
添加到seppk的响应:对于结构对象类型,他描述的问题实际上消失了(f可以给出多态类型,如∀A≤{x:Int,y:Int} .A→Int,甚至只是{x:Int,y:Int}→Int)。但是,类型推断仍然存在问题。
根本原因在于:在没有子类型的语言中,输入规则对类型强加相等约束。在类型检查期间处理这些非常好,因为通常可以使用类型的统一来立即简化它们。但是,通过子类型,这些约束被推广到不等式约束。你不能再使用统一,至少有三个不愉快的后果:
因此,对于子类型的类型推断并非不可能(90年代有很多关于这个主题的论文),但它并不是很实用。
OCaml采用了一种更简单的替代方法,它使用所谓的行多态代替子类型。这实际上是易处理的。
答案 1 :(得分:5)
当使用名义输入(即一个打字系统,其成员具有相同名称和相同类型的两个类不可互换)时,会有许多可能的类型,如下所示:
let f(obj) =
obj.x + obj.y
同时拥有成员x
和成员y
(支持+
运算符的类型)的任何类都有资格成为obj
的可能类型类型推断算法无法知道哪一个是你想要的那个。
在F#中,上面的代码需要一个类型注释。所以F#具有面向对象和类型推断,但不能同时进行(除了局部类型推断(let myVar = expressionWhoseTypeIKNow
),它总是有效)。