2016-09-19 2 views
1

У меня есть следующая иерархия, и я хотел бы определить список любых Description, но не могу определить его тип параметра.Scala более высокий тип экзистенциального типа

abstract class Context 
class Local extends Context 
class Browsing extends Context 

abstract class Fruit[C <: Context] 
class Apple[C <: Context](id: Int) extends Fruit[C] 
class Banana[C <: Context](id: Int) extends Fruit[C] 

abstract class Description[U[X <: Context] <: Fruit[X]] // U can't be covariant 
class Apples extends Description[Apple] 
class Bananas extends Description[Banana] 

В принципе, я хотел бы что-то вроде этого (который не компилируется как есть):

val l: List[Description[_]] = List(
    new Apples, 
    new Bananas 
) 

Любой путь для достижения этой цели?

+0

Как вы предполагаете использовать этот 'L'? – talex

+0

См. Http://stackoverflow.com/questions/32182694/how-to-define-an-existential-higher-kinded-type-in-scala или http://stackoverflow.com/questions/28176807/suppressing-unchecked- warning-for-a-high-kind-existential-type –

+0

Фактически, я мог бы использовать суперкласс для 'Описание' без типа параметра и использовать методы для них. Но внутри 'Описание', я имею ссылку на другие объекты, параметризованные с помощью' U', и поэтому будет вынужден создавать суперкласс для них (и их дети ... это целая иерархия). Единственное, что нужно, - сохранить как можно больше информации о типе, не создавая дополнительных абстрактных слоев. – olivier

ответ

4

Что вам нужно сделать, это:

abstract class Description[+U[X <: Context] <: Fruit[X]] 

И тогда он будет работать:

scala> List(new Apples, new Bananas) 
res40: List[Description[Fruit]] = List([email protected], [email protected]) 

Причина, почему ваш случай терпит неудачу: Когда вы делаете List(new Apples, new Bananas), потому что компилятор пытается нахождение наименьшей верхней границы (LUB) для Apples и Banana. то есть LUB для Description[Apple] и Description[Banana]. Так что вам нужно Description[_ >: Banana with Apple <: Fruit].

Как ошибка компилятора правильно говорит: Apple <: Fruit (и, конечно же, Apple>: банан с Apple). Но Description[Apple] будет только подтипом Description[_ >: Banana with Apple <: Fruit], если Description является ко-вариантом в своем параметре типа.

PS: Co-вариантность дает нам возможность иметь это: Если A <: B, а затем для M[+T], M[A] <: M[B].

Для противопоказания дисперсии M[-T], M[A] >: M[B]

Смежные вопросы