1

为什么下面的代码无法编译?

  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]forr3不够具体。但为什么不呢?
  • 还有为什么A[_<:SomeB]足够val r5: (A[_<:SomeB]) = (r3)但不适合r9
4

1 回答 1

1

首先,你的r4r5实际上是等价的。要声明类型的 val,Tuple1您需要明确:

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 中的情况(F-Bounded Polymorphic 类型和非泛型子类型的存在类型?),并且适用相同的解决方案,即通过显式指定类型参数为编译器提供一些帮助Tuple1

val r5 = Tuple1[A[_]](r3)

或者给出r3更具体的类型:

val r3: A[C] = A(c)
val r5: Tuple1[A[_]] = Tuple1(r3)

r6/也是如此Tuple2

于 2017-05-05T17:19:04.540 回答