ArticleslgStudy

computer science

Type variance

Type variance is a computer science topic covered in the lgStudy science library. This page brings together a partial reference excerpt, illustrations, worked examples, real-world applications and a short study plan, so you can understand Type variance rather than just read about it. In short: In computer programming, type variance is the relationship between subtypes of a composite type (e.g. List[Int]) and the subtypes of its components (e.g.

Type variance — main illustration
Type variance — illustration

Key takeaways

  • Type variance belongs to computer science; place it in that map before memorising details.
  • Learn the definition first, then one example that makes the definition concrete.
  • Connect Type variance to a quantity you can measure, compute or draw — that is where exam questions come from.
  • Reproduce the core statement of Type variance from memory before moving on to harder problems.

Reference excerpt

In computer programming, type variance is the relationship between subtypes of a composite type (e.g. List[Int]) and the subtypes of its components (e.g. Int). A language's chosen variance determines the relationship between, for example, a list of Cats and a list of Animals, or a function returning Cat and a function returning Animal. If the type Cat is a subtype of Animal, then an expression of type Cat should be substitutable wherever an expression of type Animal is used. Depending on the variance of the type constructor, the subtyping relation of the simple types may be either preserved, reversed, or ignored for the respective complex types. In many programming languages, for example, "list of Cat" will be a subtype of "list of Animal", because the list type constructor is covariant. This means that the subtyping relation of the simple types is preserved for the complex types. On the other hand, "function from Animal to String" is a subtype of "function from Cat to String" because the function type constructor is contravariant in the parameter type. Here, the subtyping relation of the simple types is reversed for the complex types. A programming language designer will consider variance when devising typing rules for language features such as arrays, inheritance, and generic datatypes. By making type constructors covariant or contravariant instead of invariant, more programs will be accepted as well-typed. On the other hand, programmers often find contravariance unintuitive, and accurately tracking variance to avoid runtime type errors can lead to complex typing rules. In order to keep the type system simple and allow useful programs, a language may treat a type constructor as invariant even if it would be safe to consider it variant, or treat it as covariant even though that could violate type safety.

Etymology

These terms come from the notion of covariant and contravariant functors in category theory. Consider the category C {\displaystyle C} whose objects are types and whose morphisms represent the subtype relationship ≤. (This is an example of how any partially ordered set can be considered as a category.) Then for example the function type constructor takes two types p and r and creates a new type p → r; so it takes objects in C 2 {\displaystyle C^{2}} to objects in C {\displaystyle C} . By the subtyping rule for function types this operation reverses ≤ for the first parameter and preserves it for the second, so it is a contravariant functor in the first parameter and a covariant functor in the second.

Formal definition

Suppose A and B are types, and I<U> denotes application of a type constructor I with type argument U. Within the type system of a programming language, a typing rule for a type constructor I is:

covariant if it preserves the ordering of types (≤), which orders types from more specific to more generic: If A ≤ B, then I<A> ≤ I<B>; contravariant if it reverses this ordering: If A ≤ B, then I<B> ≤ I<A>; bivariant if both of these apply (i.e., if A ≤ B, then I<A> ≡ I<B>); variant if covariant, contravariant or bivariant; invariant or nonvariant if not variant. The article considers how this applies to some common type constructors.

C# examples For example, in C#, if Cat is a subtype of Animal, then:

IEnumerable<Cat> is a subtype of IEnumerable<Animal>. The subtyping is preserved because IEnumerable<T> is covariant on T. Action<Animal> is a subtype of Action<Cat>. The subtyping is reversed because Action<T> is contravariant on T. Neither IList<Cat> nor IList<Animal> is a subtype of the other, because IList<T> is invariant on T. The variance of a C# generic interface is declared by placing the out (covariant) or in (contravariant) attribute on (zero or more of) its type parameters. The above interfaces are declared as IEnumerable<out T>, Action<in T>, and IList<T>. Types with more than one type parameter may specify different variances on each type parameter. For example, the delegate type Func<in T, out TResult> represents a function with a contravariant input parameter of type T and a covariant return value of type TResult. The compiler checks that all types are defined and used consistently with their annotations, and otherwise signals a compilation error. The typing rules for interface variance ensure type safety. For example, an Action<T> represents a first-class function expecting an argument of type T, and a function that can handle any type of animal can always be used instead of one that can only handle cats.

Arrays Read-only data types (sources) can be covariant; write-only data types (sinks) can be contravariant. Mutable data types which act as both sources and sinks should be invariant. To illustrate this general phenomenon, consider the array type. For the type Animal we can make the type Animal[], which is an "array of animals". For the purposes of this example, this array supports both reading and writing elements. We have the option to treat this as either:

covariant: a Cat[] is an Animal[]; contravariant: an Animal[] is a Cat[]; invariant: an Animal[] is not a Cat[] and a Cat[] is not an Animal[]. If we wish to avoid type errors, then only the third choice is safe. Clearly, not every Animal[] can be treated as if it were a Cat[], since a client reading from the array will expect a Cat, but an Animal[] may contain e.g. a Dog. So, the contravariant rule is not safe. Conversely, a Cat[] cannot be treated as an Animal[]. It should always be possible to put a Dog into an Animal[]. With covariant arrays this cannot be guaranteed to be safe, since the backing store might actually be an array of cats. So, the covariant rule is also not safe—the array constructor should be invariant. Note that this is only an issue for mutable arrays; the covariant rule is safe for immutable (read-only) arrays. Likewise, the contravariant rule would be safe for write-only arrays.

… excerpt ends here. Continue reading the full article.

Illustrations

Type variance illustration
Type variance illustration
Type variance illustration
Type variance illustration
Type variance illustration

Worked examples

Example 1 — a first encounter with Type variance

Start with the simplest possible case. Write down what Type variance claims or describes in one sentence, then invent the smallest concrete situation in which that sentence is true. In computer science, the smallest case is usually a single object, a single equation or a single measurement. Check that every symbol or term in your sentence has a meaning in that case.

Example 2 — changing one variable

Take the situation from Example 1 and change exactly one quantity: double it, halve it, or set it to zero. Predict what should happen to Type variance before you calculate. Comparing your prediction with the result is the fastest way to find out whether you understand the idea or only the words.

Example 3 — an exam-style question

Typical questions about Type variance ask you to (a) state it precisely, (b) apply it to given data, and (c) explain a limitation. Practise writing all three answers in under five minutes; the third part is what separates a full-mark answer from an average one.

Applications of Type variance

In research
Type variance appears in computer science research whenever the underlying quantities have to be modelled precisely. Papers usually cite it as a starting assumption and then explore where it breaks down.
In technology and industry
Engineering practice reuses Type variance in design rules, simulations and safety margins. Knowing the idea lets you read a specification sheet and understand why the numbers look the way they do.
In the classroom
Type variance is common in secondary-school and first-year university syllabi. It links to neighbouring topics Object-oriented programming, Polymorphism (computer science), Programming language comparisons, so understanding it makes those chapters shorter.
In everyday life
Look for Type variance outside the textbook — in sport, cooking, traffic, electronics or the sky above you. An example you found yourself is remembered far longer than one you were given.

Affiliate

Preply — study more efficiently by working with a personal tutor. 50% off.

How to study Type variance in 20 minutes

  1. Read the reference excerpt below once, without taking notes.
  2. Close the page and write down what Type variance means in your own words.
  3. Compare your version with the excerpt and mark what you missed.
  4. Work through the three examples above with pen and paper.
  5. Explain Type variance out loud to somebody else — or to Teacher Smith in the lgStudy chat.

Frequently asked questions

What is Type variance in simple terms?

In computer programming, type variance is the relationship between subtypes of a composite type (e.g. List[Int]) and the subtypes of its components (e.g.

Why does Type variance matter?

Because it connects several computer science ideas at once: it gives you a definition you can apply, a quantity you can calculate, and a way to check whether a result is plausible.

How should I study Type variance?

Read the excerpt, restate it from memory, then work through the examples and applications listed on this page. The five-step study plan above takes about twenty minutes.

What does this page cover?

It gives you a compact reference excerpt plus original lgStudy explanations, examples, applications and study material on Type variance.

Tags

  • Object-oriented programming
  • Polymorphism (computer science)
  • Programming language comparisons
  • Type theory

Keep exploring