【问题标题】:Why is type inference impractical for object oriented languages?为什么类型推断对于面向对象的语言不切实际?
【发布时间】:2014-03-20 09:26:20
【问题描述】:

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

我对 Haskell 等语言真正着迷的一件事是它是静态类型的,但您不必对类型进行注释(感谢 Hindley-Milner!)。

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

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

【问题讨论】:

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


【解决方案1】:

补充一下 seppk 的回答:对于结构对象类型,他描述的问题实际上消失了(可以给 f 一个多态类型,例如 ∀A ≤ {x : Int, y : Int}。A → Int,甚至只是{x : Int, y : Int} → Int)。但是,类型推断仍然存在问题。

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

  1. 约束的数量和复杂性呈组合爆炸式增长。
  2. 出现错误时必须向用户显示的信息难以理解。
  3. 某些量化形式很快就会变得无法确定。

因此,子类型的类型推断不是不可能的(90年代已经有很多关于该主题的论文),但它不是很实用。

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

【讨论】:

  • 有趣。不幸的是,我缺乏对 typing 的理论理解,无法完全理解您的观点。对另一个答案中关于使用 C++ 之类的模板概念的讨论有什么想法(最好将其描述为“编译时鸭子类型”)?
  • 从类型检查的角度来看,模板本质上只是宏。所以不是很有趣,也不是很模块化。 :)
【解决方案2】:

当使用名义类型(即成员具有相同名称和相同类型的两个类不可互换的类型系统)时,如下方法可能有多种类型:

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

任何同时具有成员x 和成员y 的类(支持+ 运算符的类型)都可以作为obj 的可能类型,并且类型推断算法将无法知道哪一个是你想要的。

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

【讨论】:

  • 我真的不明白为什么这是一个问题。类型检查器在调用 f 之前不会知道 obj 的类型吗?
  • @monoceres 我说的是对f 的定义进行类型检查,而不是调用站点。甚至可能没有对f 的调用,或者对f 的调用可能在不同的编译单元中。
  • 好的,但是如果我构建一个类型检查器来推断对象/函数/参数/无论何时使用它们的类型呢?在这种情况下,可能有许多版本的 f 取决于它的调用方式。这甚至是可能/理智的事情吗?
  • @monoceres 这意味着任何想要使用您的函数的人都需要访问您的源代码,每次使用源代码都需要重新编译,并且无法自行对库进行类型检查(即您只能在使用该库的代码上下文中对其进行类型检查)。这些是很多缺点,但它是 C++ 模板的工作方式,因此并非史无前例。
  • @sepp2k C++ 社区充分意识到这个模型有很多缺点,因此各种尝试引入模板类型(“概念”)。
猜你喜欢
  • 2010-09-06
  • 1970-01-01
  • 2017-08-02
  • 2011-06-09
  • 1970-01-01
  • 2014-11-11
  • 1970-01-01
  • 1970-01-01
  • 2013-05-19
相关资源
最近更新 更多