the beginning of this list. */ def ::[B >: A] (x: B): List[B] = new scala.collection.immutable.::(x, this) /** ... */ } First, class members that have a variant type must be immutable. Here, head has the type A, which was declared covariant (+), and indeed head was declared as a method (def). Trying to declare it as a mutable field (var) would be rejected as type error. Second, even if a data structure is immutable, it will often have methods where the parameter type occurs contravariantly. For example, consider the method :: which adds an element to the front of a list. (The implementation works by creating a new object of the similarly named class ::, the class of nonempty lists.) The most obvious type to give it would be def :: (x: A): List[A] However, this would be a type error, because the covariant parameter A appears in a contravariant position (as a function parameter). But there is a trick to get around this problem. We give :: a more general type, which allows adding an element of any type B as long as B is a supertype of A. Note that this relies on List being covariant, since this has type List[A] and we treat it as having type List[B]. At first glance it may not be obvious that the generalized type is sound, but if the programmer starts out with the simpler type declaration, the type errors will point out the place that needs to be generalized. Inferring variance It is possible to design a type system where the compiler automatically infers the best possible variance annotations for all datatype parameters. However, the analysis can get complex for several reasons. First, the analysis is nonlocal since the variance of an interface depends on the variance of all interfaces that mentions. Second, in order to get unique best solutions the type system must allow bivariant parameters (which are simultaneously co- and contravariant). And finally, the variance of type parameters should arguably be a deliberate choice by the designer of an interface, not something that just happens. For these reasons most languages do very little variance inference. C# and Scala do not infer any variance annotations at all. OCaml can infer the variance of parameterized concrete datatypes, but the programmer must explicitly specify the variance of abstract types (interfaces). For example, consider an OCaml datatype which wraps a function