Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error with definition covariant and contravariant types

Tags:

scala

I have code:

class A {
    override def toString = "object class A"
}

class B extends A {
    override def toString = "object class B"
}

class Cell[+T](init: T) {
    private[this] var current: T = init
    def get: T = current
    def set(x: T) { current = x }
}

val cB = new Cell[B](new B)
println(cB.get)
val cA: Cell[A] = cB
println(cA.get)

but I have error in line: def set(x: T) { current = x }

error: covariant type T occurs in contravariant position in type T of value x def set(x: T) { current = x }

Explain, please

like image 691
Volodymyr Avatar asked Jan 11 '13 12:01

Volodymyr


2 Answers

Contravariant positions for a type are (among others) any positions that allow you to pass an instance of that type to a method. So all method parameter types are in contravariant positions. Since you declared T as covariant ( +T), the compiler won't allow this. Your only options are:

  • make T invariant
  • modify the set method such that it returns a new instance of Cell and Cell thus becomes immutable.
  • remove the set method, also making Cell immutable

If the compiler allowed you to have a set method as you implemented it, that would make the type system unsafe, since it would allow you to write:

val cs:Cell[String] = new Cell("")
val ca:Cell[Any] = cs
ca.set(5)
val s:String = cs.get //boom
like image 51
Kim Stebel Avatar answered Oct 26 '22 23:10

Kim Stebel


The short answer is that you cannot have a mutable container which is covariant. Assuming this compiled, then in your example, the last two lines could read:

val cA: Call[A] = cB
cA.set(new A)

The first line would be allowed, because a Cell[B] is a Cell[A] due to the use of +T. And then the second line is allowed too - because of course you can set a Cell[A] to hold an A.

But now, cB.get returns an instance of A, not a B! This doesn't make any sense, and there is no way to resolve this contradiction while still allowing covariance in Cell's type parameter.


For a longer, more formal/comprehensive answer, see this question: Scala covariance/contravariance

like image 20
Andrzej Doyle Avatar answered Oct 26 '22 23:10

Andrzej Doyle