简体   繁体   中英

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, eg, type T = List[R] does not compile either, although List is covariant.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM