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.

- 72,696
- 27
- 242
- 420

- 10,185
- 12
- 59
- 110
2 Answers
The classic example is functions, taking the Scala interface for a function with a single argument:
trait Function1[-T1, +R]
Which is contravariant (the -
) for the argument, and covariant (the +
) for the return type.
Why?
Imagine you have these classes:
class Timelord { ... }
class Doctor extends Timelord { ... }
class Enemy { ... }
class Dalek extends Enemy { ... }
If you have a method that takes, as a parameter, a Doctor => Enemy
function; then it's okay to supply an instance of TimeLord => Enemy
. It'll still accept instances of Doctor
.
So TimeLord => Enemy
is a subclass of Doctor => Enemy
because TimeLord
is a superclass of Doctor
, it's contravariant in that parameter.
Likewise, a function returning a Dalek
is valid when you need a function returning some Enemy
, because a Dalek
is-an Enemy
So Doctor => Dalek
is a subclass of Doctor => Enemy
because Dalek
is a subclass of Enemy
, it's covariant in that parameter.

- 72,696
- 27
- 242
- 420

- 49,540
- 9
- 105
- 155
-
1AKA, anywhere we need a `Dalek` that can exterminate `Doctor`s, a `Dalek` of `Any` will do :-) – fommil Nov 09 '13 at 23:33
-
1so, according to `Function[-R, +T]`, is `Doctor => Enemy` the most appropriate function signature? I'm saying this because, if R is contravariant, then R should be the most sub-type, and, since T is covariant, it should be the most super-type? – Kevin Meredith Feb 19 '14 at 20:38
Essentially anywhere where you want to make use of both parametric polymorphism (generics) and inheritance, you will probably end up wanting either declaration site variance (+
/-
), use site variance (wildcards), or more likely, both.
Polymorphic types are usually fairly high-level abstractions, so while your domain objects may not need variance annotations, it's likely that code that you write to manipulate your domain objects will need to use variance annotations, at least if your domain objects are part of inheritance hierarchies, which seems very frequent.
If you take a look at essentially any library or framework, you'll find frequent use of variance annotations. If you're abstracting your "real world" application correctly, you'll probably be writing lots of libraries to support it, with a small core of critical business logic nicely decoupled from all of the support infrastructure. All that support infrastructure will probably make frequent use of variance annotations, too.

- 49,540
- 9
- 105
- 155

- 4,560
- 1
- 26
- 29