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
4
votes
2 answers

How to contramap over functions?

Given: class Contravariant (f :: * -> *) where contramap :: (a -> b) -> f b -> f a The following code is rejected. I'm expecting to get String -> Bool (a predicate) as a result of contra-mapping Int -> Bool over String -> Int. I feel stupid as I…
sevo
  • 4,559
  • 1
  • 15
  • 31
4
votes
1 answer

Cannot convert from class to generic interface

EDIT: Updated to include actual code. I am having an issue with some custom generic interfaces and I am not entirely sure what to do. The error I'm getting is: Cannot convert from Map to IMap That error pops up when I try to pass Map as a…
CStrach
  • 88
  • 1
  • 7
4
votes
1 answer

Can't seem to get Generic Covariance/Contravariance to work

Suppose I have the following code: public interface IBaseMessage { } public interface IMessageProcessor where T : IBaseMessage { void Process(T msg); } public class RRMessage : IBaseMessage { //something here …
Denis
  • 11,796
  • 16
  • 88
  • 150
4
votes
2 answers

Why constrain to interface in generic typing?

What would be the point of making a constraint for an interface type on a generic in C#? For example, public interface IHandler where T : IProcessor { void Handle(T command); } Wouldn't it be better to simply inherit IProcessor as a…
user1789573
  • 515
  • 2
  • 8
  • 23
4
votes
0 answers

Why is only contravariance allowed for method input parameters according to the Liskov Substitution Principle?

I was trying to find good examples of why contra-variance is the only variance allowed for method input parameters according to the Liskov Substitution Principle, but until now none of the examples has completely answered ,y doubts. I was trying to…
nbro
  • 15,395
  • 32
  • 113
  • 196
4
votes
1 answer

How is IEnumerable Contra-variant?

This post (http://blogs.msdn.com/b/brada/archive/2005/01/18/355755.aspx) says IEnumerable is Contra-variant. However type T is co-variant because it is an out parameter. So in what context is IEnumerable Contra-variant ?? Hope I am not…
gbackmania
  • 772
  • 3
  • 7
  • 17
4
votes
4 answers

The type cannot be used as type parameter 'T' in the generic type or method 'BaseController'. There is no implicit reference

I'm trying to create a generic to simplify my codes (it's a web api project), but at somehow it's ended up becoming more complicated than I expected. What I'm trying to implement is something like this: To simplify my whole real code, this is what…
Martin Valentino
  • 1,002
  • 2
  • 11
  • 26
4
votes
1 answer

Detect variance on generic type parameters of interfaces

Is there a way to reflect on an interface to detect variance on its generic type parameters and return types? In other words, can I use reflection to differentiate between the two interfaces: interface IVariant { R DoSomething(A…
Water Cooler v2
  • 32,724
  • 54
  • 166
  • 336
4
votes
1 answer

Scala implementation of a generic Heap

I'm trying to implement a very basic implementation of a generic Heap, and while I love the type checker, this is one of these occasions where I feel it's fighting me every step of the way. The simplest expression I could write was: trait Heap[A] { …
Nicolas Rinaudo
  • 6,068
  • 28
  • 41
4
votes
0 answers

Why are covariance and contravariance supported only for interfaces but not classes?

Is it some fundamental restriction (I really see none) or as Eric Lippert usually says: nobody just has proved it's worth implementing feature?
Pavel Voronin
  • 13,503
  • 7
  • 71
  • 137
4
votes
2 answers

Contravariant method argument type

wiki Contravariant_method_argument_type says overriding method has the subtyping rule as function type, but no language except one support contravariant argument type. I also not able to come up with any idea of benefit to use that. example: class…
WeiChing 林煒清
  • 4,452
  • 3
  • 30
  • 65
4
votes
2 answers

Generic type inference with interface inheritance (co(ntra)-variance?) in C# 3

I have the following two generic types: interface IRange where T : IComparable interface IRange : IRange where T : IComparable ^---------^ | …
Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
4
votes
4 answers

Contravariant Value Types

I have created this interface for my Repositories. public interface IRepository where T: class { IEnumerable Find(Expression> predicate); IEnumerable FindAll(); T FindSingle(TKey id); void Create(T…
Lotok
  • 4,517
  • 1
  • 34
  • 44
4
votes
1 answer

Contravariantly converting Guava Predicates

I have a Predicate and need an equivalent Predicate. Predicate provideIsSentientPredicate() { // Won't compile -- cannot convert from Predicate to Predicate return…
Robert Cooper
  • 1,270
  • 9
  • 11
4
votes
2 answers

How to make generic class that contains a Set of only its own type or subtypes as Children?

abstract class Animal { } class Mammal : Animal { } class Dog : Mammal { } class Reptile : Animal { } class AnimalWrapper where T : Animal { public ISet> Children { get; set; } } class Program { public static void…
johansson
  • 1,467
  • 2
  • 10
  • 9