# How (and why) to make immutable collections covariant

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 19.5, “How (and why) to make immutable collections covariant.”

## Problem

You want to create a collection whose elements can’t be changed (they’re immutable), and want to understand how to specify it.

## Solution

You can define a collection of immutable elements as invariant, but your collection will be much more flexible if you declare that your type parameter is covariant. To make a type parameter covariant, declare it with the `+` symbol, like `[+A]`.

Covariant type parameters are shown in the Scaladoc for immutable collection classes like `List`, `Vector`, and `Seq`:

```class List[+T]
class Vector[+A]
trait Seq[+A]```

By defining the type parameter to be covariant, you create a situation where the collection can be used in a more flexible manner.

To demonstrate this, modify the example from the previous recipe slightly. First, define the class hierarchy:

```trait Animal {
def speak
}

class Dog(var name: String) extends Animal {
def speak { println("Dog says woof") }
}

class SuperDog(name: String) extends Dog(name) {
override def speak { println("I'm a SuperDog") }
}```

Next, define a `makeDogsSpeak` method, but instead of accepting a mutable `ArrayBuffer[Dog]` as in the previous recipe, accept an immutable `Seq[Dog]`:

```def makeDogsSpeak(dogs: Seq[Dog]) {
dogs.foreach(_.speak)
}```

As with the `ArrayBuffer` in the previous recipe, you can pass a sequence of type `[Dog]` into `makeDogsSpeak` without a problem:

```// this works
val dogs = Seq(new Dog("Fido"), new Dog("Tanner"))
makeDogsSpeak(dogs)```

However, in this case, you can also pass a `Seq[SuperDog]` into the `makeDogsSpeak` method successfully:

```// this works too
val superDogs = Seq(new SuperDog("Wonder Dog"), new SuperDog("Scooby"))
makeDogsSpeak(superDogs)```

Because `Seq` is immutable and defined with a covariant parameter type, `makeDogsSpeak` can now accept collections of both `Dog` and `SuperDog`.

## Discussion

You can demonstrate this by creating a collection class with a covariant type parameter.

To do this, create a collection class that can hold one element. Because you don’t want the collection element to be mutated, define the element as a `val`, and make the type parameter covariant with `+A`:

`class Container[+A] (val elem: A)`

Using the same type hierarchy as shown in the Solution, modify the `makeDogsSpeak` method to accept a `Container[Dog]`:

```def makeDogsSpeak(dogHouse: Container[Dog]) {
dogHouse.elem.speak()
}```

With this setup, you can pass a `Container[Dog]` into `makeDogsSpeak`:

```val dogHouse = new Container(new Dog("Tanner"))
makeDogsSpeak(dogHouse)```

Finally, to demonstrate the point of adding the `+` symbol to the parameter, you can also pass a `Container[SuperDog]` into `makeDogsSpeak`:

```val superDogHouse = new Container(new SuperDog("Wonder Dog"))
makeDogsSpeak(superDogHouse)```

Because the `Container` element is immutable and its mutable type parameter is marked as covariant, all of this code works successfully. Note that if you change the `Container`’s type parameter from `+A` to `A`, the last line of code won’t compile.

As demonstrated in these examples, defining an immutable collection to take a covariant generic type parameter makes the collection more flexible and useful throughout your code.

## The Scala Cookbook

This tutorial is sponsored by the Scala Cookbook, which I wrote for O’Reilly:

You can find the Scala Cookbook at these locations: