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
0
votes
3 answers

Covariant type FParam occurs in contravariant position in type Seq[FParam] of value guesses

Consider this simple example: trait Optimizer[+FParam, FRes] { def optimize( fn: (FParam) => FRes, guesses: Seq[FParam] // <--- error ) } It doesn't compile, because Covariant type FParam occurs in contravariant position in type…
user267817
0
votes
1 answer

How to make the Type in lamba expression be the type of derived class from a generic base class

I have the following code: public abstract class EntityMapperBase { protected void Map(string columnName, Func, object> func) { _mappings.Add(columnName, func); } protected object…
adriaanp
  • 2,064
  • 2
  • 22
  • 40
0
votes
1 answer

Covariant interface with contravariant interface as member property

I have an interface which defines a reader and a writer for any IFoo. public interface IFoobarStore where E : class, IFoobar { IFoobarReader GetReader(); IFoobarWriter GetWriter(); } IFoobarStore is covariant. IFoobarStore…
Daniel L.
  • 437
  • 3
  • 15
0
votes
0 answers

Can't assign contravariant object

I created the following SuperNode: public interface ISuperNodeWrite where TNode : ISuperNodeWrite { T Data { set; } TNode Left { set; } } public class SuperNode : ISuperNodeWrite> { public…
Briefkasten
  • 1,964
  • 2
  • 25
  • 53
0
votes
1 answer

c# .net 4.0 Covariant vs Contravariant

I'm trying to get something working and struggling with the below when using Contravariance. My understanding is Covariance is where you can return a derived type from a base type. Contravariance is where you can pass in a derived type from a base…
tones
  • 3
  • 3
0
votes
1 answer

How Do I cast between 2 types that implement the same interface

I have a overlapping data objects that need to be given to at least one, possibly more, of several calculation methods to produce a common data object. I think this is best solved by implementing both covarriance contravariance but I haven't been…
Kludge
  • 19
  • 1
  • 8
0
votes
1 answer

Real world use of Contravariance and Covariance in .net

I Want to know the real world scenario where we use Contravariance and Covariance with program.I saw various blogs but I am still confused where I can implement.
user2147163
  • 87
  • 1
  • 4
  • 13
0
votes
1 answer

Java - Bounds on class public API

I have a ModelDecorator helper. I want it to have the following public API class ModelDecorator{ public static ModelDecorator create(Class clazz); public T from(SUPER fromInstance); } So, given classes A, B extends A, …
Jason Oviedo
  • 459
  • 1
  • 5
  • 16
0
votes
2 answers

Covariance confusion. Can't assign tuples of implemented interfaces to list of tuples

Preface: I am aware that there are a lot of questions and answers about covariance and contravariance but I'm still feeling muddled and not sure what solution to implement. I have two interfaces whose implementations are intended to be used together…
Zac
  • 1,722
  • 1
  • 19
  • 22
0
votes
1 answer

Why can't class-wide upper-bound constraints be covariant and lower-bound constraints be contravariant in Hack?

Regardless of the variance of parameter on the left side, the constraints placed on Ta and Tb in the following declaration fail the typecheck: class A<+TCov, -TCon, [±]Ta as TCov, [±]Tb super TCon> { public function __construct(private Ta $ta,…
concat
  • 3,107
  • 16
  • 30
0
votes
1 answer

Is it a mistake in msdn documentation for covariance at delegates?

In this msdn documentation about covariance and contravariance it is explained that out keyword is used to declare a generic parameter covariant. You can declare a generic type parameter covariant by using the out keyword. Then is given an example…
meJustAndrew
  • 6,011
  • 8
  • 50
  • 76
0
votes
1 answer

Simulate making library interfaces variant

There are several places where my code significantly benefits from using variance to take better advantage of polymorphism. What I would really like to do, which I know is not possible, is something like this: abstract class A { // In my perfect…
hypehuman
  • 1,290
  • 2
  • 18
  • 37
0
votes
1 answer

Scala: what's the reason of 'covariant type R occurs in invariant position'?

Given the following example code: trait Gen[T, +R] { def follow[K](gen: Gen[R, K]): Gen[T, K] def i: T def j: R } case class GenImpl[T, R](i: T, j: R) extends Gen[T, R] { override def follow[K](gen: Gen[R, K]): Gen[T, K] = { …
tribbloid
  • 4,026
  • 14
  • 64
  • 103
0
votes
2 answers

Contravariance/Covariance, why can't cast this?

Let's face it, I am still having some difficulties to understand the constrains when it's time to use covariance and contravariance in generics. I wonder, why if I have this: public interface IFasterListCov {} public interface…
sebas
  • 1,045
  • 12
  • 27
0
votes
1 answer

Scala Co and Contravariance

Yes! Another of this question, and yes i already read alot of this questions in stackoverflow and still don't understand this concept and it's application. So, i'm i new comer to Scala, and like many people i still didn't get the concept of…
Kennedy Oliveira
  • 2,141
  • 2
  • 20
  • 25