tri*_*oid 7 scala type-inference abstract-type path-dependent-type dependent-type
我有一个简单的案例来测试scala的类型推断能力:
trait Super1[S] {
final type Out = this.type
final val out: Out = this
}
trait Super2[S] extends Super1[S] {
final type SS = S
}
case class A[S](k: S) extends Super2[S] {}
val a = A("abc")
implicitly[a.type =:= a.out.type]
// success
implicitly[a.Out =:= a.out.Out]
// success
implicitly[a.SS =:= a.out.SS]
implicitly[a.SS <:< a.out.SS]
implicitly[a.out.SS <:< a.SS]
// oops
Run Code Online (Sandbox Code Playgroud)
最后 4 行的错误如下所示:
[Error] /home/peng/git-spike/scalaspike/common/src/test/scala/com/tribbloids/spike/scala_spike/AbstractType/InferInheritance.scala:28: Cannot prove that a.SS =:= Super2.this.SS.
[Error] /home/peng/git-spike/scalaspike/common/src/test/scala/com/tribbloids/spike/scala_spike/AbstractType/InferInheritance.scala:29: Cannot prove that a.SS <:< Super2.this.SS.
[Error] /home/peng/git-spike/scalaspike/common/src/test/scala/com/tribbloids/spike/scala_spike/AbstractType/InferInheritance.scala:30: Cannot prove that Super2.this.SS <:< a.SS.
three errors found
Run Code Online (Sandbox Code Playgroud)
显然 Scala 编译器在这些情况下搞砸了:如果我移动:
final type Out = this.type
final val out: Out = this
Run Code Online (Sandbox Code Playgroud)
在Super2
它下面会编译成功。我的问题是:为什么现状推理算法在这种情况下不起作用?以及如何重写我的代码来规避编译器的这个问题?
如果a.SS =:= a.out.SS
那么我们应该能够使用其中之一来代替另一个。是这样吗?
不。
val x: a.SS = "hello"
val y: a.out.SS = "hello"
Run Code Online (Sandbox Code Playgroud)
编译这个我得到:
ScalaFiddle.scala:29: error: type mismatch;
found : lang.this.String("hello")
required: Super2.this.SS
(which expands to) S
val y: a.out.SS = "hello"
Run Code Online (Sandbox Code Playgroud)
看起来 Scalaa.SS
确实明白这一点String
,这并不奇怪。
但显然a.out.SS
不是String
,而是…… S
。
奇怪的是,尽管这显然是错误的,但它仍然有效:
val b = A(1)
implicitly[a.out.SS =:= b.out.SS]
Run Code Online (Sandbox Code Playgroud)
如果您只是定义out
为类型,this.type
那么您的代码就可以工作。
我能想到的最好的办法是,在定义 的类型时out
,Scala 无法将 所表示的实际类型关联起来S
,因此通过查看的out
类型只有泛型类型。SS
out
S
该类型Out
似乎确实理解 所表示的实际类型S
,因此这是有效的:
implicitly[a.SS =:= a.Out#SS]
implicitly[a.SS <:< a.Out#SS]
implicitly[a.Out#SS <:< a.SS]
Run Code Online (Sandbox Code Playgroud)
并且这正确地无法编译:
val b = A(1)
implicitly[a.Out#SS =:= b.Out#SS]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
105 次 |
最近记录: |