# Is +A or -A? right?

Could someone please explain to me the difference between covariance and contravariance?
I understand invariance.

1 Like

The +A is covariant and the -A is contravariant. This alters the subtyping relationship between the two parameterized types of the main type based on the type parameter. To help make this discussion concrete, letâ€™s assume a `class Foo[A]` to start with, them change it to `class Foo[+A]` and `class Foo[-A]`.

With `class Foo[A]`, `Foo` is invariant with `A`. What that means is that `Foo[Type1]` and `Foo[Type2]` are completely unrelated types, regardless of whether a subtyping relationship exists between `Type1` and `Type2`. Where this surprises people is that if `Apple` is a subtype of `Fruit`, `Foo[Apple]` will not be a subtype of `Foo[Fruit]` and you canâ€™t pass an instance of `Foo[Apple]` into a function that expects `Foo[Fruit]`. That is the easy one, which you have said you understand, but it is good to make it clear.

The declaration `class Foo[+A]` makes `Foo` covariant with `A`. In this situation, `Foo[Type1]` is a subtype of `Foo[Type2]` iff `Type1` is a subtype of `Type2`. That means that now we can pass a `Foo[Apple]` into a function that expects a `Foo[Fruit]`. The `List` type in Scala in covariant, so you can do this. You might wonder why you have things that arenâ€™t covariant given that covariance just seems to make sense. The answer is that if the `Foo` type allows you to pass in things of type `A`, then being covariant can cause problems. Consider an `Array` instead of a `List`. Because `Array` is mutable if I were allowed to pass an `Array[Apple]` into a function that accepts an `Array[Fruit]`, that function could add some other type of `Fruit`, say a `Banana` into the `Array`. That canâ€™t be allowed with an `Array[Apple]`, and that is why `Array` canâ€™t be covariant. In a simple (and incomplete) sense, covariant parameters canâ€™t be passed into methods, of the type, but they can be returned. So you can get values from a `List`, but you canâ€™t set them.

If you declare `class Foo[-A]` then `Foo` is contravariant with `A`. This is the one that I think people generally find less intuitive, and it isnâ€™t used as much. In this case, `Foo[Type1]` is a subtype of `Foo[Type2]` iff `Type1` is a supertype of `Type2`. That means that `Foo[Fruit]` is a subtype of `Foo[Apple]`. That might not seem to make sense, but it is exactly what you want when you have methods where values of that type are passed in, but not returned. If I had a write-only collection that I could just add stuff to, call it a `WList`, then it would make sense to use a `WList[Fruit]` in a place where a `WList[Apple]` was expected. It would be safe because the function that expects a `WList[Apple]` can only add apples and it is safe to add apples to a `WList[Fruit]`. There is a classic example in the Scala libraries in the form of `Function1[-T1, +R]`. One function type is a subtype of another type if the input argument is a supertype and the return type is a subtype. Running with the fruit example, `Apple => Fruit` is a subtype of `Fruit => Apple` because if I expect a function of the type `Apple => Fruit` I will only give it apples and my expectation is that it will return fruit. Given this, it is perfectly safe for my to pass the apple to a `Fruit => Apple` and get back an apple that I use as a general fruit.

3 Likes

Another example is `Function[-Z, +Y]`

If the contract is to require an apple to provide any car
then you should not complain if you receive a sports car when giving any fruit

Hello,

The drawing alone makes this post worth checking out:
http://blog.originate.com/blog/2016/08/10/cheat-codes-for-contravariance-and-covariance/

Best, Oliver

1 Like

â€śâ€¦but afterwards the nightmares got worse, since now they included clowns and burning pandas. I stayed up for days.â€ť