Scala list of any and list of something extending Any. What is a difference?

395 Views Asked by At

Could anyone explain what is difference between: Seq[Any] and Seq[_ <: Any] ?
To my eye, I can put everything in both cases as everything extends Any.

2

There are 2 best solutions below

12
On BEST ANSWER

Here there's no difference because Seq is covariant. So:

  1. Seq[Any] is a subtype of Seq[_ <: Any] because that _ could be Any;

  2. Seq[_ <: Any] is a subtype of Seq[Any] because whatever you put instead of _ you'll get a subtype of Seq[Any].

If you replace Seq by some invariant F (e.g. Set), Set[Any] is a subtype of Set[_ <: Any] but not vice versa. Set[_ <: Any] is the common supertype of Set[Any], Set[String], Set[Int] etc.

In more detail:

  1. Set[_ <: Any] is a shorthand for Set[T] forSome { T <: Any }.

  2. Set[T] forSome { T <: Any } is the supertype of all Set[T] for types T which satisfy T <: Any. The specification says

    The set of values denoted by the existential type T forSome {Q} is the union of the set of values of all its type instances.

    but that's the same thing.

So code like

val set1: Set[String] = ??? 
val set2: Set[_ <: Any] = set1

will compile (try it!). And it still will if you replace String by any other type (_ <: ... is not a type). But

val set1: Set[String] = ??? 
val set2: Set[Any] = set1

won't.

1
On

I'll just add to @AlexeyRomanov's answer a quote of specific place in Scala spec:

3.2.12 Existential Types

Simplification Rules

4.An existential type forSome { } where contains a clause type [tps]>:<: is equivalent to the type ′ forSome { } where results from by replacing every covariant occurrence of in by and by replacing every contravariant occurrence of in by .

https://scala-lang.org/files/archive/spec/2.13/03-types.html#simplification-rules

Seq[_ <: Any] is Seq[T] forSome { type T <: Any}, the occurrence of T in Seq[T] is covariant because Seq is covariant, so Seq[T] forSome { type T <: Any} =:= Seq[Any] forSome { type T <: Any} =:= Seq[Any] (the last step also uses simplification rule #2).