1

I have the following hierarchy and I would like to define a list of any Description but can't figure out its parameter type.

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]

Basically, I would like something like this (which doesn't compile as is):

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

Any way to achieve this?

olivier
  • 1,007
  • 8
  • 14
  • How you expect to use that `l`? – talex Sep 19 '16 at 14:38
  • See http://stackoverflow.com/questions/32182694/how-to-define-an-existential-higher-kinded-type-in-scala or http://stackoverflow.com/questions/28176807/suppressing-unchecked-warning-for-a-higher-kinded-existential-type – Alexey Romanov Sep 19 '16 at 14:53
  • Actually, I could use a superclass for `Description` without parameter type and use the methods on those. But inside `Description`, I have reference to other objects parameterized with `U` and would be therefore forced to create superclass for those as well (and their children… it's a whole hierarchy). The only point is to keep as much information about the type as I can without creating any additional abstract layers. – olivier Sep 19 '16 at 14:55

1 Answers1

4

What you need to do is this:

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

And then it will work:

scala> List(new Apples, new Bananas)
res40: List[Description[Fruit]] = List(Apples@6a808ae5, Bananas@4f4d77e8)

The reason on why your case fails is: When you do List(new Apples, new Bananas), because the compiler tries finding the least upper bound (LUB) for Apples and Banana. i.e. LUB for Description[Apple] and Description[Banana]. So what you need is Description[_ >: Banana with Apple <: Fruit].

As the compiler error rightly says: Apple <: Fruit (and of-course Apple >: Banana with Apple). But Description[Apple] will only be a subtype of Description[_ >: Banana with Apple <: Fruit] if Description is co-variant in its type parameter.

PS: Co-variance gives us the ability to have this: If A <: B and then for M[+T], M[A] <: M[B].

For contra-variance M[-T], M[A] >: M[B]

Jatin
  • 31,116
  • 15
  • 98
  • 163