Jam*_*ies 4 generics scala type-inference existential-type
在Scala中使用存在类型时,编译器似乎将存在主体的每个用法推断为不同的类型参数,即使它们实际上是相同的.
对于一个简单的人为例子 - 给出以下代码
class Box[T](value:T){
def get:T = value
def contains(check:T):Boolean = value == check
}
Run Code Online (Sandbox Code Playgroud)
我可以做以下事情
val b1 = new Box(1)
b1.contains(b1.get)
Run Code Online (Sandbox Code Playgroud)
但是当使用存在类型时......
val b2 : Box[_] = new Box(1)
b2.contains(b2.get)
Run Code Online (Sandbox Code Playgroud)
我收到以下错误(在scala 2.11.7中
[error] /private/tmp/exttest/test.scala:53: type mismatch;
[error] found : (some other)_$6(in value b2)
[error] required: _$6(in value b2)
[error] b2.contains(b2.get)
Run Code Online (Sandbox Code Playgroud)
我的假设是编译器会理解_$6
在两种情况下都使用相同的类型参数,但是它似乎失去了跟踪并将它们视为单独的类型.
我是否从根本上误解了存在类型的某些内容,或者这是Scala编译器中的错误 - 如果是这样,是否有最佳实践来解决它?
这可能更多是限制而不是错误.
通常,解决此问题的简单方法是将敏感代码移动到通用方法:
def containsSelf[T](box: Box[T]): Boolean =
box.contains(box.get)
val b2 : Box[_] = new Box(1)
containsSelf(b2)
Run Code Online (Sandbox Code Playgroud)
或者使用类型成员而不是泛型来设计您的类.这可能是更多的样板,但确切地完成了你想要的:
trait Box {
type Element
def get: Element
def contains(check: Element): Boolean
}
object Box {
type Aux[T] = Box { type Element = T }
def apply[T](value: T): Box.Aux[T] =
new Box {
type Element = T
def get = value
def contains(check: T) = value == check
}
}
val b2: Box = Box(1)
b2.contains(b2.get)
Run Code Online (Sandbox Code Playgroud)