Suppose I want to make a list of integers. And suppose, for the sake of argument, that add
is implemented without generics.
def add(element: A): List[A]
For the sake of this example, let's suppose we have some way of producing an "empty" list.
def emptyList[A]: List[A] = /* some magic */
Now I want to make my list of integers.
(1 to 10).foldRight(emptyList) { (x, acc) => acc.add(x) }
Oops! We have a problem! When I call emptyList
, Scala is going to infer the most general type, and since A
is covariant, it's going to assume Nothing
. That means I just tried to add an integer to a list of nothing. We could fix this problem with an explicit type signature,
(1 to 10).foldRight(emptyList[Int]) { (x, acc) => acc.add(x) }
But, really, that's not solving the problem. It adds nothing to readability and just requires the user to do extra work. Realistically, I should be able to append a number to a list of nothing. It's just that, if I choose to do so, I can't meaningfully call it a list of Nothing
anymore. Hence, if we define
def add[B >: A](element: B): List[B]
Now, I can start with a List[Nothing]
and add an Int
to it. The thing I get out isn't a List[Nothing]
anymore; it's a List[Int]
, but I can do it. If I take that List[Int]
and come along later and add a String
to it, well I can do that too, but now I have a virtually useless List[Any]
.