What are covariance and contravariance?
Covariance and contravariance are just monotonicity and anti-monotonicity, applied to types ordered by subtyping.<p>That is: if we have a function <i>on types</i>, say, the function `f` defined by:<p><pre><code>    f(x) = Int -> x
</code></pre>
Then we say `f` is covariant because it is monotone: it preserves the subtype ordering on its argument. That is:<p><pre><code>    if x <: y, then f(x) <: f(y)
</code></pre>
Similarly, if we consider `f` defined by:<p><pre><code>    f(x) = x -> Int
</code></pre>
then this `f` is contravariant because it is anti-monotone: it reverses the subtype ordering on its argument. That is:<p><pre><code>    if x <: y, then f(y) <: f(x)
</code></pre>
People tend to find covariance more intuitive than contravariance; unless the issue is pointed out, they tend to assume everything is covariant. They see a type, say:<p><pre><code>    dog -> dog
</code></pre>
and they assume "oh, every dog is an animal, so I can put 'animal' in place of 'dog' and it'll be more general (i.e. a supertype)". This is false, as the article points out.