Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala Set.contains doesn't give expected type mismatch error

I'm new to Scala, and I'm struggling to understand why I sometimes don't get a type error when supplying the wrong argument to Set.contains

Here's a quick example using the REPL (2.9.1.final):

scala> val baz = Map("one" -> 1, "two" -> 2)
baz: scala.collection.immutable.Map[java.lang.String,Int] = Map(one -> 1, two -> 2)

scala> baz.values.toSet.contains("asdf")
res3: Boolean = false

Why didn't I get a type mismatch there?

If I assign baz.values.toSet to another val, and call contains on that, I do get type checking:

scala> val bling = baz.values.toSet
bling: scala.collection.immutable.Set[Int] = Set(1, 2)

scala> bling.contains("asdf")
<console>:10: error: type mismatch;
 found   : java.lang.String("asdf")
 required: Int
              bling.contains("asdf")
                             ^

Stupid mistake, language subtlety, or compiler bug?

like image 911
mrg Avatar asked Mar 02 '12 16:03

mrg


1 Answers

OK, so Set is invariant in its type parameter and it works exactly like it should

scala> Set(1, 2, 3) contains "Hi"
<console>:8: error: type mismatch;
 found   : java.lang.String("Hi")
 required: Int
              Set(1, 2, 3) contains "Hi"
                                    ^

But, like you say:

scala> Map('a -> 1, 'b -> 2, 'c -> 3).values.toSet contains "Hi"
res1: Boolean = false

The only conclusion we can reasonably come to is that the type of the Set in question is not Set[Int]. What happens if we explicitly tell scala we want a Set[Int]? The same piece of code with an explicit type parameter works just fine (i.e. it does not compile):

scala> Map('a -> 1, 'b -> 2, 'c -> 3).values.toSet[Int] contains "Hi"
<console>:8: error: type mismatch;
 found   : java.lang.String("Hi")
 required: Int
              Map('a -> 1, 'b -> 2, 'c -> 3).values.toSet[Int] contains "Hi"
                                                                        ^

The issue is the inferred type parameter being passed to the toSet method. Scala is obviously taking the contains "Hi" into account and inferring the lub of Int and String (i.e. Any)

like image 126
oxbow_lakes Avatar answered Nov 18 '22 05:11

oxbow_lakes