Questions tagged [contravariance]

Within the type system of a programming language, covariance and contravariance refers to the ordering of types from narrower to wider and their interchangeability or equivalence in certain situations (such as parameters, generics, and return types)

Within the type system of a programming language, a typing rule or a type conversion operator is:

covariant if it preserves the ordering, ≤, of types, which orders types from more specific to more generic;

contravariant if it reverses this ordering, which orders types from more generic to more specific;

invariant if neither of these applies.

These terms come from category theory, which has a general definition of covariance and contravariance that unifies the computer science definition of these terms with the definition used in vector spaces.

This distinction is important in considering argument and return types of methods in class hierarchies. In object-oriented languages such as Python, if class B is a subtype of class A, then all member functions of B must return the same or narrower set of types as A; the return type is said to be covariant. On the other hand, if the member functions of B take the same or broader set of arguments compared with the member functions of A, the argument type is said to be contravariant. The problem for instances of B is how to be perfectly substitutable for instances of A. The only way to guarantee type safety and substitutability is to be equally or more liberal than A on inputs, and to be equally or more strict than A on outputs. Note that not all programming languages guarantee both properties in every context, and that some are unnecessarily strict; they are said not to support covariance or contravariance in a given context; the behavior of some programming languages is discussed below.

Typical examples:

The operator which constructs array types from element types is usually covariant on the base type: since String ≤ Object then ArrayOf(String) ≤ ArrayOf(Object). Note that this is only correct (i.e. type safe) if the array is immutable; if insert and remove operators are permitted, then the insert operator is covariant (e.g. one can insert a String into an ArrayOf(Object)) and the remove operator is contravariant (e.g. one can remove an Object from an ArrayOf(String)). Since the mutators have conflicting variance, mutable arrays should be invariant on the base type.

Let f be a function with a parameter of type T and let g be a function with a parameter of type S, both with the same return type. If T ≤ S, then g ≤ f. g can replace f anywhere, since it cares less about the type of its parameter, and both return the same type. Because the subtype relation between the argument type and the functions is reversed, the function type is said to be contravariant on its argument type.

Let f be a function that returns a value of type T and let g be a function that returns a value of type S, both with the same parameter type. If T ≤ S, then f ≤ g. f can replace g anywhere, since it returns only a subset of all possible values returned by g, and both take the same argument. Because the subtype relation between the argument type and the functions is preserved, the function type is said to be covariant on its return type.

In object-oriented programming, substitution is also implicitly invoked by overriding methods in subclasses: the new method can be used where the old method was invoked in the original code. Programming languages vary widely on their allowed forms of overriding, and on the variance of overridden methods' types.

540 questions
22
votes
1 answer

Why are contravariant parameter types in Java not allowed for overriding?

When overriding a method of a superclass, Java allows the return type to be covariant. Why are contravariant parameter types in contrast not allowed when overriding methods?
Will
  • 2,858
  • 6
  • 33
  • 50
21
votes
4 answers

Does I re-implement I if I is convertible to I by variance conversion?

interface ICloneable { T Clone(); } class Base : ICloneable { public Base Clone() { return new Base(); } } class Derived : Base, ICloneable { new public Derived Clone() { return new Derived(); } } Given these…
Michael Liu
  • 52,147
  • 13
  • 117
  • 150
21
votes
2 answers

Why generic interfaces are not co/contravariant by default?

For example IEnumerable interface: public interface IEnumerable : IEnumerable { IEnumerator GetEnumerator(); } In this interface the generic type is used only as a return type of interface method and not used as a type of method…
Konstantin Tarkus
  • 37,618
  • 14
  • 135
  • 121
21
votes
3 answers

How to find the minimum covariant type for best fit between two types?

There's IsAssignableFrom method returns a boolean value indicates if one type is assignable from another type. How can we not only test if they are assignable from or to each other, but also know the minimum covariant type for best fit? Consider…
Ken Kin
  • 4,503
  • 3
  • 38
  • 76
20
votes
1 answer

Generic wildcards in variable declarations in Scala

In Java I might do this: class MyClass { private List list; public void setList(List l) { list = l; } } ...assuming that (MyImpl implements MyInterface) of course. What is the analog for this in Scala, when…
oxbow_lakes
  • 133,303
  • 56
  • 317
  • 449
20
votes
2 answers

OCaml variance (+'a, -'a) and invariance

After writing this piece of code module type TS = sig type +'a t end module T : TS = struct type 'a t = {info : 'a list} end I realised I needed info to be mutable. I wrote, then : module type TS = sig type +'a t end module T : TS =…
Lhooq
  • 4,281
  • 1
  • 18
  • 37
20
votes
1 answer

covariant type T occurs in contravariant position

I know this question has been asked before, but either the answers don't apply to this case, or I don't understand them. Basically, why doesn't the following (simple example that recreates my problem) work ? class Test[+T] { var list: List[T] =…
sksamuel
  • 16,154
  • 8
  • 60
  • 108
18
votes
1 answer

Functions are contravariant in their argument types and co-variant in their return types

I have read this and this answers before posting this question, but I am still a bit unclear in my understanding of this topic as explained below: I understand what covariant and contravariant independently mean. If I have classes as below: class…
rgamber
  • 5,749
  • 10
  • 55
  • 99
18
votes
4 answers

Why is Action> covariant?

This is something I'm having a hard time wrapping my head around. I understand that Action is contravariant and is probably declared as such. internal delegate void Action(T t); However, I don't understand why an Action> is…
Tejas Sharma
  • 3,420
  • 22
  • 35
17
votes
4 answers

What are the benefits of covariance and contravariance?

C# 4.0 is going to support covariance and contravariance. But I don't clearly understand the benefits of this new feature. Can you explain me (clearly) why we need it?
Delta76
  • 13,931
  • 30
  • 95
  • 128
17
votes
5 answers

Why do we need new keywords for Covariance and Contravariance in C#?

Can someone explain why there is the need to add an out or in parameter to indicate that a generic type is Co or Contra variant in C# 4.0? I've been trying to understand why this is important and why the compiler can't just figure it…
JoshBerke
  • 66,142
  • 25
  • 126
  • 164
17
votes
5 answers

Understanding Covariance and Contravariance in C# 4.0

I watched a video about it on Channel 9 but I didn't really understand it much. Can someone please give me a simple example about these that's easy to understand? After that maybe how it would be used in practice?
Joan Venge
  • 315,713
  • 212
  • 479
  • 689
16
votes
2 answers

Generic Covariance and contravariance

Consider the code snippet. IList obj=new List(); IEnumerable obj1 = obj; But if i write ICollection obj2 = obj; it throws me a compile time error. Cannot implicitly convert type…
Ashley John
  • 2,379
  • 2
  • 21
  • 36
16
votes
2 answers

How are co- and contra-variance used in designing business applications?

I know about using co- and contravariance in the standard library (e.g. collections and trait Function) I wonder how co- and contravariance are used in design of "real world" business applications.
Michael
  • 10,185
  • 12
  • 59
  • 110
16
votes
3 answers

Generic Variance in C# 4.0

Generic Variance in C# 4.0 has been implemented in such a way that it's possible to write the following without an exception (which is what would happen in C# 3.0): List intList = new List(); List objectList = intList; [Example…
Daniel May
  • 8,156
  • 1
  • 33
  • 43
1 2
3
35 36