Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I alias a covariant generic type parameter

The following code does not compile (in Scala 2.11):

case class CovariantClass[+R](value: R) {
  type T = R
  def get: R = value
}

object Main {
  def main(args: Array[String]): Unit ={
    println(CovariantClass[String]("hello").get)
  }
}

The error message is:

Error:(4, 8) covariant type R occurs in invariant position in type R of type T
  type T = R
       ^

Why can't I alias a covariant type parameter? If I remove the line type T = R, the code compiles and prints hello, so the alias seems to be the problem. Unfortunately, this means that I cannot create an alias for more complex types, e.g., type T = List[R] does not compile either, although List is covariant.

like image 858
Kulu Limpa Avatar asked Oct 18 '14 00:10

Kulu Limpa


2 Answers

From the scala spec:

The right-hand side of a type alias is always in invariant position.

This means that you cannot create the alias T and specify a variant type R on the right-hand side. The same applies to List[R], because it is also covariant.

You can, however provide a type alias with a type parameter:

case class CovariantClass[+R](value: R) {
  type T[+R] = List[R]
  def get: R = value
}

If you find yourself wanting to alias the type parameter R, you should probably just name it something else in the first place.

like image 137
Michael Zajac Avatar answered Nov 17 '22 02:11

Michael Zajac


It's forbidden because it would allow a program that isn't correct, that's always the rule. You could rewrite it like this:

case class CovariantClass[+R](value: R) {
  type T <: R
  def get: R = value
}

As for an example of how it breaks, consider this:

case class CovariantClass[+R](value: R) {
  type T = Int
  def get: R = value
  def put(x: T) {}
  def put2(x: R) {}
}

Because of how T is defined, it is invariant. That means it can be used in places where covariant types cannot, such as seen above. Notice that put compiles but put2 does not.

like image 32
Daniel C. Sobral Avatar answered Nov 17 '22 03:11

Daniel C. Sobral