0

I was very surprised by the fact that we can assign List[Nothing] To any list. Like this

val nums : List[Number] = List(1, 2, 3, 4) val nums_2 : List[Integer] = Nil; // <--- extends List[Nothing] val ints : List[Integer] = nums // error: type mismatch 

So, this is very confusing. In this article they said that

Because lists are covariant in Scala, this makes scala.collection.immutable.Nil an instance of List[T], for any element of type T.

What is that supposed to mean?

1

1 Answer 1

1

If a generic type is covariant in a given type parameter (denoted by a + before that type parameter in the type's definition, like abstract class List[+T]), that means that if you have two types T and U, such that T is a subtype of U, List[T] is also a subtype of List[U].

So a variable that's supposed to hold a List[Any] can also hold a List[String] because String is a subtype of Any and a variable that's supposed to hold a List[Whatever] can also hold a List[Nothing] because Nothing is a subtype of every type (it's kinda magical in that regard).

Sign up to request clarification or add additional context in comments.

3 Comments

Got it, the key thing is that is's immutable. Thank you.
The key thing is that the List[T] type constructor is covariant in T. The reason that is type-safe is that List[T] is immutable. In general: if you can only read from it, it's safe to be covariant (e.g. List[T]). If you can only write to it, it's safe to be contravariant (e.g. Logger[T]). If you can both read and write, it's unsafe to be either co- or contravariant, it must be invariant. (See Java's arrays which are mutable but covariant, and what do we get? ArrayStoreException.) That's why FunctionN[-T1, -T2, -T3, …, +R] is contravariant in its parameter types and covariant in …
… its return type.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.