存在类型

时间:2011-06-07 15:21:16

标签: scala existential-type

(更新:简化代码并说明它应该起作用的原因)

如何修复此代码?:

case class Sub[B <: Seq[_] : Manifest](b: B) {
  def foo[B2 >: B <: Seq[_] : Manifest](other: Sub[B2]) : B2 =  {
    println(manifest[B])
    println(manifest[B2])

    // next line doesn't compile 
    // other.b ++ b
    other.b 
  }

}

如果我取消注释行other.b ++ b,我会收到错误:

<console>:13: error: Cannot construct a collection of type That with elements of type Any based on a collection of type Repr.
           other.b ++ b
                   ^

如果我发表评论,代码会编译并运行它:

scala> Sub(List(1,2)).foo(Sub(Seq(4,5)))
scala.collection.immutable.List[Int]
scala.collection.Seq[Int]
res0: Seq[Int] = List(4, 5)

因此,编译器知道元素的类型为List[Int]Seq[Int]。连接它们应该没有问题。

注意:我希望保留使用'B2&gt;:B',因为我需要推断它。

2 个答案:

答案 0 :(得分:4)

此时你已经失去了Seq [_]的类型,所以唯一可能得到的B是Seq [Any] ......因此,你可以安全地将b归于Seq [Any](b: Seq [Any])++ b2。

仅仅因为你在B中保留了B&lt;:Seq [_]并不意味着你可以从序列中恢复存在主义类型。

答案 1 :(得分:1)

如果你不依赖于使用存在类型,那么这应该有效:

case class Sub[T, B[X] <: Seq[X]](b: B[T]) {
  def foo[B2[X] <: Seq[X]](other: Sub[T,B2]) =
     other.b ++ b
}