繁体   English   中英

为什么Scala不推导出特征类型参数?

[英]Why Scala doesn't deduce trait type parameters?

trait foo[F] {
  def test: F
}

class ah extends foo[(Int,Int) => Int] {
  def test = (i: Int,j: Int) => i+j
}

所以现在的问题是,为什么斯卡拉知道这么聪明类型不能只是演绎型(Int,Int) => Int从类型test问我,而不是指定它? 或者仍有可能吗? 或许这可以得到一些我没有想到的想法的支持。

您的问题基本上是“为什么Scala只有本地类型推断”或等效“为什么Scala没有非本地类型推断”。 答案是:因为设计师不愿意。

有几个原因。 一个原因是本地类型推断的最合理的替代方法是全局类型推断,但在Scala中这是不可能的:Scala具有单独的编译和模块类型检查,因此编译器只有整个全局视图的时间点。程序。 实际上,Scala具有动态代码加载功能,这意味着在编译时整个代码甚至不需要存在! 在Scala中根本不可能进行全局类型推断。 我们能做的最好的事情是“整个编译单元类型推断”,但这也是不可取的:它意味着你是否需要类型注释取决于你是否在多个单元中编译代码或只编译一个。

另一个重要原因是模块边界处的类型注释用作复核,类似于类型的复式簿记。 请注意,即使在具有全局类型推断的语言如Haskell)中,强烈建议在模块边界和公共接口上放置类型注释。

第三个原因是全局类型推断有时会导致混淆的错误消息,当类型检查器在类型注释中失败时,类型推断器会快速地推断出越来越不合理的类型,直到它最终放弃到远处的位置。远离实际错误(可能只是一个简单的错字),其类型错误只与错误站点的原始类型相切。 例如,这有时会发生在Haskell中。 Scala设计人员非常重视有用的错误消息,以至于他们愿意牺牲语言功能,除非他们能够弄清楚如何使用良好的错误消息来实现它们。 (请注意,即使使用Scala非常有限的类型推断,您也可以获得“有用的”消息,因为“预期Foo得到了Product with Serializable ”。)

但是,Scala的本地类型推断在此示例中可以执行的操作是在另一个方向上工作,并从返回类型的test推断出匿名函数的参数类型:

trait foo[F] {
  def test: F
}

class ah extends foo[(Int, Int) ⇒ Int] {
  def test = (i, j) ⇒ i + j
}

(new ah) test(2, 3) //=> 5

对于您的特定示例,基于继承推断类型参数可能不明确:

trait A
trait B extends A

trait Foo[T] {
    val x: T
}

trait Bar extends Foo[?] {
    val x: B
}

可以进入的类型? 可以是AB 这是Scala不会推断可能含糊不清的类型的一般示例。

现在,您正确地观察到它们之间存在相似性

class Foo[T](x: T)

trait Foo[T] { x: T }

我看到一些人的工作可能会推广相似性(但我现在似乎无法找到它)。 从理论上讲,这可以允许基于成员对类型参数进行类型推断。 但我不知道它是否会达到这一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM