экзистенциальные типы - PullRequest
4 голосов
/ 07 июня 2011

(ОБНОВЛЕНИЕ: упрощен код, а также показано, почему он должен работать)

Как я могу исправить этот код?:

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>: B' так, как мне нужно, чтобы оно было выведено.

Ответы [ 2 ]

4 голосов
/ 08 июня 2011

Вы потеряли типы Seq [_] к этому моменту, поэтому единственно возможный B, который вы можете получить, это Seq [Any] ... Таким образом, вы можете приписать b к Seq [Any] безопасно (b:Seq [Any]) ++ b2.

То, что вы сохранили B в B <: Seq [_], не означает, что вы можете восстановить экзистенциальный тип из последовательности. </p>

1 голос
/ 09 июня 2011

Если вы не привязаны к использованию экзистенциального типа, это должно работать:

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