Search code examples
scalascala-3

Why is `contains` on collections not requiring the correct type?


How come this compiles:

scala> val x: Vector[Int] = Vector(1,2,3)
val x: Vector[Int] = Vector(1, 2, 3)

scala> x.contains("hello")
val res4: Boolean = false

scala> x.contains(List(Map("anything" -> 3.14)))                                                 
val res5: Boolean = false

EDIT:

This is separate from this other question in which the element type of the collection is inferred (to Any) whereas here it is explicitly set (to Int).


Solution

  • The signature is (in 3.0.0; I recommend always including the language/library version in such questions, and for Scala in particular)

    def contains[A1 >: A](elem: A1): Boolean
    

    This means that the argument type must be a supertype of Int, and "hello" is inferred to be Any which is indeed such a supertype.

    The reason for the signature instead of maybe more expected

    def contains(elem: A): Boolean
    

    is that that signature wouldn't allow Vector and other collections to be covariant.

    Specifically, if a Vector[Int] extends Vector[Any], and you can call contains(Any) on a Vector[Any], you must also be able to call it on a Vector[Int].