Variance in Scala
"Variance" describes the subtyping relationship between types. In scala, the possiblities are: covariance, contravariance and invariance.
Covariance allows the type to be more specific. For example, if A is a substype of B -> then F[A] is also a subtype of F[B]. A more concrete example:
class Animal
class Dog extends Animal
class Container[+T](value: T){ getValue: T = valule }
val animalContainer: Container[Animal] = new Container(new Dog) // this is valid!
contravariance allows a subtype to be more general. For example: if A is a subtype of B -> F[B] is also a subtype of F[A]
class Printer[-T] { def print(value: T): Unit = println(value) }
val dogPrinter: Printer[Dog] = new Printer[Animal]
Invariant is neither covariant OR contravariant