[英]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
}
So the question is, why Scala known to be so smart about types cannot just deduce type (Int,Int) => Int
from the type of test
asking me instead to specify it? 所以现在的问题是,为什么斯卡拉知道这么聪明类型不能只是演绎型
(Int,Int) => Int
从类型test
问我,而不是指定它? Or It is still possible? 或者仍有可能吗? Or maybe this is backed by some thoughts that I don't have in mind.
或许这可以得到一些我没有想到的想法的支持。
Your question is basically "why does Scala have only local type inference" or equivalently "why does Scala not have non-local type inference". 您的问题基本上是“为什么Scala只有本地类型推断”或等效“为什么Scala没有非本地类型推断”。 And the answer is: because the designers don't want to.
答案是:因为设计师不愿意。
There are several reasons for this. 有几个原因。 One reason is that the most reasonable alternative to local type inference is global type inference, but that's impossible in Scala: Scala has separate compilation and modular type checking, so there simply is no point in time where the compiler has a global view of the entire program.
一个原因是本地类型推断的最合理的替代方法是全局类型推断,但在Scala中这是不可能的:Scala具有单独的编译和模块类型检查,因此编译器只有整个全局视图的时间点。程序。 In fact, Scala has dynamic code loading, which means that at compile time the entire code doesn't even need to exist yet!
实际上,Scala具有动态代码加载功能,这意味着在编译时整个代码甚至不需要存在! Global type inference is simply impossible in Scala.
在Scala中根本不可能进行全局类型推断。 The best we could do is "whole-compilation-unit type inference", but that is undesirable, too: it would mean that whether or not you need type annotations depends on whether or not you compile your code in multiple units or just one.
我们能做的最好的事情是“整个编译单元类型推断”,但这也是不可取的:它意味着你是否需要类型注释取决于你是否在多个单元中编译代码或只编译一个。
Another important reason is that type annotations at module boundaries serve as a double-check, kind of like double-entry book keeping for types. 另一个重要原因是模块边界处的类型注释用作复核,类似于类型的复式簿记。 Note that even in languages with global type inference like Haskell, it is strongly recommended to put type annotations on module boundaries and public interfaces.
请注意,即使在具有全局类型推断的语言(如Haskell)中,强烈建议在模块边界和公共接口上放置类型注释。
A third reason is that global type inference can sometimes lead to confusing error messages, when instead of the type checker failing at a type annotation, the type inferencer happily chugs along inferring increasingly non-sensical types, until it finally gives up at a location far away from the actual error (which might just be a simple typo) with a type error that is only tangentially related to the original types at the error site. 第三个原因是全局类型推断有时会导致混淆的错误消息,当类型检查器在类型注释中失败时,类型推断器会快速地推断出越来越不合理的类型,直到它最终放弃到远处的位置。远离实际错误(可能只是一个简单的错字),其类型错误只与错误站点的原始类型相切。 This can sometimes happen in Haskell, for example.
例如,这有时会发生在Haskell中。 The Scala designers value helpful error messages so much that they are willing to sacrifice language features unless they can figure out how to implement them with good error messages.
Scala设计人员非常重视有用的错误消息,以至于他们愿意牺牲语言功能,除非他们能够弄清楚如何使用良好的错误消息来实现它们。 (Note that even with Scala's very limited type inference, you can get such "helpful" messages as "expected
Foo
got Product with Serializable
".) (请注意,即使使用Scala非常有限的类型推断,您也可以获得“有用的”消息,因为“预期
Foo
得到了Product with Serializable
”。)
However, what Scala's local type inference can do in this example, is to work in the other direction, and infer the parameter types of the anonymous function from the return type of test
: 但是,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
For you particular example, inferring type parameters based on inheritance can be ambiguous: 对于您的特定示例,基于继承推断类型参数可能不明确:
trait A
trait B extends A
trait Foo[T] {
val x: T
}
trait Bar extends Foo[?] {
val x: B
}
The type that could go in the ?
可以进入的类型
?
could be either A
or B
. 可以是
A
或B
This is a general example of where Scala will not infer types that could be ambiguous. 这是Scala不会推断可能含糊不清的类型的一般示例。
Now, you are correct to observe that there is a similarity between 现在,您正确地观察到它们之间存在相似性
class Foo[T](x: T)
and 和
trait Foo[T] { x: T }
I have seen work by some into possibly generalizing the similarity (but I can't seem to find it right now). 我看到一些人的工作可能会推广相似性(但我现在似乎无法找到它)。 That could, in theory, allow type inference of type parameters based on a member.
从理论上讲,这可以允许基于成员对类型参数进行类型推断。 But I don't know if it will ever get to that point.
但我不知道它是否会达到这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.