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
1 answer

"in" generic modifier interaction with "where" clause

Suppose the following: interface IBase { } interface IChild : IBase { } interface IFace where T : IBase { } private class MyClass : IFace { } void Do1() { // This is fine IFace impl = new MyClass(); } void Do2()…
Tefatika
  • 9
  • 2
0
votes
0 answers

Not able to assign a delegate with more derived type parameter to a delegate with less derived type parameter - Generic Delegates

I am trying to understand the contravariance in generic delegates. In the following code I am able to assign the delegate sgd1 to sgd2(covariance). Even if the type parameter of sgd4 is base type of the type parameter of sgd3 why am I not able to…
ravikiran
  • 33
  • 6
0
votes
1 answer

How can I create a method whose argument is a function whose argument can be an object from any class extending a given class?

I have classes B and C inheriting from A. public class A { } public class B : A { } public class C : A { } I have some functions that take objects B and C as arguments: public void FunB(B obj) { } public void FunC(C obj) { } I want to create a…
xavier
  • 1,860
  • 4
  • 18
  • 46
0
votes
0 answers

Why cannot I return T from a contravariant delegate with "in T" and why cannot I take T as parameter for a covariant delegate with "out T"?

I am completely new in C# covariant and contravariant concept. I have been following YouTube tutorials and MSDN docs, but they are still confusing. It will be very kind of you if please explain why cannot I return T from a contravariant delegate…
0
votes
1 answer

Returning a class that implements a variant interface

Background: I have three Silverlight Pages, that implement my interface: interface IPageWithData where T : Entity { void SetData(T obj); } public class APage : Page, IPageWithData { /* Implementation */ } public class BPage : Page,…
Kornelije Petak
  • 9,412
  • 15
  • 68
  • 96
0
votes
1 answer

Is there a Scala pattern for nested generics allowing my inner generic type to have polymorphism?

I want to be able to pass a parameter of the same type in a function in the outer nested generic class, but also have a polymorphic internal generic class as well - allowing me to use an abstract base class/trait for InnerShell and OuterShell both.…
0
votes
2 answers

How can I filter a list in Java using a predicate function?

Consider the following code: ICondition searchCondition, scopeCondition... List filtered = CollectionUtil.filter( Arrays.asList(searchCondition, scopeCondition), CollectionUtil.isNonNull); It fails to compile: "The method…
Dustin Getz
  • 21,282
  • 15
  • 82
  • 131
0
votes
0 answers

type-agnostic implementation of a generic interface

I have some classes that override Equals and GetHashCode, but every now and then I need to compare by reference. So I have written a ReferenceEqualityComparer like here: https://stackoverflow.com/a/35520207/5333340 Note that…
Kjara
  • 2,504
  • 15
  • 42
0
votes
0 answers

C++ template contravariance without std::function

Consider: #include #include class Base {}; class Derived : public Base {}; template class Effect { public: virtual void call(T& val) = 0; // Additional Functions... }; class BaseEffect : public…
Djeurissen
  • 377
  • 5
  • 15
0
votes
1 answer

C# enforce set of classes to be used together

Here is my use case. Say I have a game with two modes: CoolMode and NormalMode. Both game modes are very different but share three common objects: Input, Score, and Judger. Each mode would have different implementations, but could be called from the…
user5182794
0
votes
2 answers

Why contravariant position in Builder is marked as invariant by compiler?

I want to understand why scala compiler emits error for the following snippet: import scala.collection.mutable class X[+A, +C] { val x = mutable.Map.empty[Int, mutable.Builder[A, C]] } The error ouput: :13: error: covariant type A…
Naitree
  • 1,088
  • 1
  • 14
  • 23
0
votes
0 answers

c# contravariance and covariance: cannot convert from implementation to interface

Experts, what is wrong here: I have these interfaces: public interface IEvent {} public interface ISingleEventModelChangeInterrogator where TEvent : IEvent { List GetChangedCandidates(object context, TEvent…
Klaus Nji
  • 18,107
  • 29
  • 105
  • 185
0
votes
1 answer

C# Covariance in generic types

I can not get around C# covariance for this simple example, here is how I defined my model: interface IResponse { } interface ICommand where TResponse : IResponse { } class Response : IResponse { } class Command :…
MK.Persia
  • 13
  • 2
0
votes
1 answer

Question about contravariant parameter used in method parameters

I have read a good article introducing the covariance and contracovariance http://bartdesmet.net/blogs/bart/archive/2009/04/15/14377.aspx Contravariant parameters should only occur in input positions: method parameters, set-only properties or…
q0987
  • 34,938
  • 69
  • 242
  • 387
0
votes
1 answer

How to have one covariant parameter in a class as well as a function to transform it?

I have a very simple class: case class Foo[+T](t: T) Now I want to add a argument to transform T to Int. For specific reasons, I do not want to use a typeclass, an implicit or any inheritance based solution because this is really what I am…
pm42
  • 21
  • 2