为什么以下代码无法编译?
trait B[T <: B[T]]
case class A[T <: B[T]](t: T)
class C() extends B[C]
val c: C = new C()
val r2: A[_] = A(c) //compiles
val r3: A[_] = A(c) //compiles fine
val r4: A[_] = r3 //compiles fine
val r5: (A[_]) = (r3) //compiles fine
val r6: (A[_], A[_]) = (r3, r3) // does not compile, strange
它给出了:
Error:(68, 22) type arguments [_$7] do not conform to class A's type parameter bounds [T <: _experiment.akka_persistence.Test2.B[T]]
val r6:(A[_],A[_])=(r3,r3)
编辑:
以下是相关的自包含代码段:
import scala.language.existentials
trait B[T <: B[T]]
case class A[T <: B[T]](t: T)
class C() extends B[C]
val c: C = new C()
type SomeB = T forSome { type T <: B[T] }
val r3: A[_<:SomeB] = A(c) //compiles fine
val r4: A[C] = A(c) //compiles fine
val r5: (A[_<:SomeB]) = (r3) //compiles fine
val r6:((_<:SomeB),((_<:SomeB))) = (c,c) // compiles fine
val r7:(A[_<:SomeB],((_<:SomeB))) = (A(c),c) // compiles fine
val r8:(A[_<:SomeB],(A[_<:SomeB])) = (A(c),A(c)) // compiles fine
val r10:(A[_<:SomeB],(A[_<:SomeB])) = (A(c),r4) // compiles fine
val r9:(A[_<:SomeB],(A[_<:SomeB])) = (A(c),r3) // does not compile
r4
的类型必须为A[C]
,然后才会r10
进行编译。 A[_<:SomeB]
的{{1}}不够具体。但为什么不呢? r3
A[_<:SomeB]
足够val r5: (A[_<:SomeB]) = (r3)
而r9
呢?答案 0 :(得分:1)
首先,您的r4
和r5
实际上是等效的。要声明类型Tuple1
的val,您需要明确:
val r5: Tuple1[A[_]] = Tuple1(r3)
然后你会发现它也会因同样的错误而失败。
在REPL中:
scala> Tuple1(r3)
<console>:24: warning: inferred existential type (A[_$1],) forSome { type _$1 }, which cannot be expressed by wildcards, should be enabled
by making the implicit value scala.language.existentials visible.
This can be achieved by adding the import clause 'import scala.language.existentials'
or by setting the compiler option -language:existentials.
See the Scaladoc for value scala.language.existentials for a discussion
why the feature should be explicitly enabled.
Tuple1(r3)
^
<console>:24: error: type arguments [_$1] do not conform to class A's type parameter bounds [T <: B[T]]
Tuple1(r3)
^
您看到给定的存在类型r3
编译器将元组推断为(A[_$1],) forSome { type _$1 }
。
这种情况确实类似于@jhegedus(Existential types for F-Bounded Polymorphic types and non-generic subtypes?)中的情况,同样的解决方案适用,即通过明确指定Tuple1
的类型参数给编译器一些帮助:
val r5 = Tuple1[A[_]](r3)
或者给r3
更具体的类型:
val r3: A[C] = A(c)
val r5: Tuple1[A[_]] = Tuple1(r3)
r6
/ Tuple2