3
votes

Trying the following in 2.8.1/2.9.0.1 REPL, the first gives an error.

val l = List(Vector(1,2), List(3,4,5))
error: type mismatch;
 found   : scala.collection.immutable.Vector[Int]
 required: scala.collection.immutable.Seq[Int]{def companion:     scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq[Any]]; protected def thisCollection: Seq[Int]{def companion: scala.collection.generic.GenericCompanion[Seq[Any]]}; def dropRight(n: Int): scala.collection.immutable.Seq[Int]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq[Any]]}; def takeRight(n: Int): scala.collection.immutable.Seq[Int]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq[Any]]}; def slice(start: Int,end: Int): scala.collection.immutable.Seq[Int]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable....
      val l = List(Vector(1,2), List(3,4,5))
                         ^
:5: error: type mismatch;
 found   : List[Int]
 required: scala.collection.immutable.Seq[Int]{def companion:     scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq[Any]]; protected def thisCollection: Seq[Int]{def companion: scala.collection.generic.GenericCompanion[Seq[Any]]}; def dropRight(n: Int): scala.collection.immutable.Seq[Int]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq[Any]]}; def takeRight(n: Int): scala.collection.immutable.Seq[Int]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq[Any]]}; def slice(start: Int,end: Int): scala.collection.immutable.Seq[Int]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq[Any]]}; def take(n: Int):...
       val l = List(Vector(1,2), List(3,4,5))
                                    ^

While this succeeds:

val l = List[Seq[Int]](Vector(1,2), List(3,4,5))
//evaluates fine to List[Seq[Int]] = List(Vector(1, 2), List(3, 4, 5))

What is the type scala tries to infer in the first case? Is it a Seq with a structural type? Why can't it unify Vector and List? Is this some missing feature yet, or is it this way (requiring explicit type def) in order to to prevent shooting myself in the foot?

2
works with 2.9.1 scala> val l = List(Vector(1,2), List(3,4,5)) l: List[scala.collection.immutable.Seq[Int]] = List(Vector(1, 2), List(3, 4, 5))Ido Tamir

2 Answers

7
votes

This was evidently a bug in the type inferencer which has now been fixed in scala 2.9.1:

Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Server VM, Java 1.6.0_18).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import collection.immutable._
import collection.immutable._

scala>  List(Vector(1, 2, 3), List(4, 5))
res0: List[scala.collection.immutable.Seq[Int]] = List(Vector(1, 2, 3), List(4, 5))
0
votes

Based on daniel's answer here, Scala does not use Hindley-Milner type inference and instead does local type inference, moving left to right.

In your first declaration, the first list member is Vector[Int] so Scala says "okay I have a List[Vector[Int]] but then when it gets to the second list element, a List[Int], it becomes unable to unify this with Vector[Int]. The generics must be a problem for the inferencer, because lists containing numbers and strings can be properly inferred to be List[Any].

Something related: vectors and lists can interoperate in 2.9.0.1 across the == operator.

scala> List[Int](1,2,3) == Vector[Int](1,2,3)
res2: Boolean = true

scala> List[Int](1,2,3) == Vector[Int](1,12,3)
res3: Boolean = false