Gon*_*lez 3 scala type-inference traits
trait foo[F] {
def test: F
}
class ah extends foo[(Int,Int) => Int] {
def test = (i: Int,j: Int) => i+j
}
Run Code Online (Sandbox Code Playgroud)
所以问题是,为什么Scala知道如此聪明的类型不能简单地(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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
307 次 |
| 最近记录: |