Because collections are typically covariant in their element type*, a collection of a subtype may be passed where a super type is expected:
trait Animal { def name: String }
case class Dog(name: String) extends Animal
object Animal {
def printAnimalNames(animals: Seq[Animal]) = {
animals.foreach(animal => println(animal.name))
}
}
val myDogs: Seq[Dog] = Seq(Dog("Curly"), Dog("Larry"), Dog("Moe"))
Animal.printAnimalNames(myDogs)
// Curly
// Larry
// Moe
It may not seem like magic, but the fact that a Seq[Dog] is accepted by a method that expects a Seq[Animal] is the entire concept of a higher-kinded type (here: Seq) being covariant in its type parameter.
* A counterexample being the standard library's Set