ron
ron

Reputation: 9396

Scala - Why can't infer List of Seq for a list containing Vector and List?

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?

Upvotes: 3

Views: 1702

Answers (2)

Ray Toal
Ray Toal

Reputation: 88488

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

Upvotes: 0

oxbow_lakes
oxbow_lakes

Reputation: 134340

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))

Upvotes: 7

Related Questions