In Scala (2.10) if I ask for a List(1.0, 2) then I get a List[Double], as expected.
But…
if I ask for a Map(1.0 -> 'A', 2 -> 'B') I get a Map[AnyVal, Char]. I’d like the keys to be of type Double. Asking for Map[Double, Char](1.0 -> 'A', 2 -> 'B) gives a type mismatch on ‘2’.
This I find most confusing! Is it not inconsistent?
Aside: List[(Double, Char)]((1.0, 'A'), (2, 'B')).toMap gives me a Map[Double, Char] though.
If you look into Scala’s type hierarchy, you can see that the primitive types are not in a sub-type/super-type relationship. However, there is a mechanism called numeric widening which for example allows you to call a method that takes a
Doubleargument, by passing in say anInt. TheIntthen is automatically “widened” toDouble.This is the reason that
List(1.0, 2)gives youList[Double].But the
Mapconstructor takesTuple[A, B]arguments. The numeric widening doesn’t apply to higher order types, so the target type inference doesn’t work for you if you mix numeric types.Moreover, the arrow operator
->gets in your way:This is another limitation of the type inference I think. Writing a tuple
a -> bis syntactic sugar for(a, b), provided by the implicit methodany2ArrowAssoconPredef. Without this indirection, if you construct theTuple2directly, it works:So the numeric widening still doesn’t work, but at least you can enforce the type:
A final example showing numeric widening working: