Search code examples
scalagenericsexistential-type

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


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.


Solution

  • 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.