Существующие типы для F-ограниченных полиморфных типов и неуниверсальных подтипов?
У меня есть два подтипа, которые я должен быть F-ограниченным полиморфным по типу A
и подтип одного из этих подтипов, т.е.
trait A[T <: A[T]] {
def x: T
}
trait Ter extends A[Ter]
trait For extends A[For]
trait C extends Ter
Далее я пытаюсь реализовать конкретный тип
case class F2(l: List[A[_]]) extends For {
def x: For = F2(l.map(_.x))
}
Но это не компилируется с:
<console>:11: error: type mismatch;
found : List[Any]
required: List[A[_]]
def x: For = F2(l.map(_.x))
^
Итак, Google говорит, что мне нужно использовать экзистенциальные типы, что имеет смысл, поэтому я пытаюсь:
import scala.language.existentials
type SomeA = T forSome { type T <: A[T] }
case class F1(l: List[SomeA]) extends For {
def x: For = F1(l.map(_.x))
}
Но теперь я сталкиваюсь с новой проблемой, когда пытаюсь
trait Example {
val b: Ter
val c: C
val d: For
// Works fine
val l1: List[A[_]] = List(b, c, d)
// But this doesn't work, fails to compile (see below)
val l2: List[SomeA] = List(b, c, d)
val f1 = F1(l2)
}
Ошибка компиляции:
<console>:22: error: type mismatch;
found : C
required: SomeA
(which expands to) T forSome { type T <: A[T] }
val l2: List[SomeA] = List(b, c, d)
^
Почему я получаю эту ошибку? конечно C
это подтип Ter
что, в свою очередь, является подтипом A[Ter]
, следовательно C
это подтип A[Ter]
следовательно, существует T
а именно Ter
такой, что C
это подтип A[T]
, следовательно C
это подтип SomeA
,
Как будто транзитивность подтипов не работает. Когда я взломаю это с c.asInstanceOf[SomeA]
мой код компилируется, и мои модульные тесты проходят. Может ли это быть ошибка компилятора?
Я тоже думал что List[A[_]]
был сильнее, чем печатать List[SomeA]
т.е. первый говорил, что список состоит из A[T]
какой-то фиксированный тип T
где последний говорит, что список состоит из A[T]
где T
не исправлено
BOUNS Если вы можете объяснить, почему принятый в настоящее время ответ работает, то есть почему компилятор не может определить, что тип допустим без надписи.
1 ответ
Я думаю, компилятору нужна помощь. Следующее должно работать:
val l2 = List[SomeA](b, c: Ter, d)