【问题标题】:Scala - Why can't infer List of Seq for a list containing Vector and List?Scala - 为什么不能推断包含 Vector 和 List 的列表的 Seq 列表?
【发布时间】:2011-09-14 05:50:32
【问题描述】:

在 2.8.1/2.9.0.1 REPL 中尝试如下,第一个报错。

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

虽然这会成功:

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

scala 在第一种情况下试图推断的类型是什么?它是具有结构类型的 Seq 吗?为什么不能统一 Vector 和 List?这是一些缺少的功能,还是这种方式(需要显式类型 def)以防止射击自己的脚?

【问题讨论】:

  • 适用于 2.9.1 scala> val l = List(Vector(1,2), List(3,4,5)) l: List[scala.collection.immutable.Seq[Int] ] = List(向量(1, 2), List(3, 4, 5))

标签: scala type-inference seq


【解决方案1】:

这显然是类型推断器中的一个错误,现已在 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))

【讨论】:

  • 顺便说一下,这是 2.9.1 中存在但应该在 2.10 中修复的另一个错误:List(collection.mutable.Seq(1,2), collection.mutable.Set(3,4,5))。错误:“类型参数 [Any] 不符合 ...”
【解决方案2】:

根据 daniel 的回答 here,Scala 不使用 Hindley-Milner 类型推断,而是进行本地类型推断,从左到右移动。

在您的第一个声明中,第一个列表成员是 Vector[Int],所以 Scala 说“好的,我有一个 List[Vector[Int]],但是当它到达第二个列表元素 List[Int] 时,它变得无法将它与Vector[Int]。泛型对推理器来说肯定是个问题,因为包含数字和字符串的列表可以被正确地推断为List[Any]

相关的:向量和列表可以在 2.9.0.1 中通过 == 运算符进行互操作。

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

【讨论】:

  • 与 val s = Set(List(1,2,3), List("xyz")) 有什么区别,哪个很好用?它还具有从左到右的不同类型(但仅限叶类型)。
  • 那么为什么List(1, 2.0, "3")不会出现同样的问题呢?恐怕你错了
  • @oxbow_lakes 很高兴知道谢谢!那么这里的协议是什么?删除答案还是留在这里?
  • 您建议的概念似乎是正确的,但它存在两个问题。首先,在一个普通的参数列表(即,不是隐式参数列表)中,所有类型都是在不相互引用的情况下推断出来的。为了实际效果,您可以将它们的推理视为并行的。其次,这个工厂不带多个参数,只带一个 vararg。此参数的类型将根据每个参数给出的边界计算。由于错误,它不起作用。
  • 感谢有用的 cmets;这为我解决了问题。 oxbow_lakes 指出了这个错误。也许这个错误的发生是因为在这种情况下泛型更难推断。至少现在已经修复了。我想我应该把这个答案记下来,但我认为你的评论应该保持不变,其他人也应该如此。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-13
  • 1970-01-01
  • 1970-01-01
  • 2018-08-24
  • 1970-01-01
  • 1970-01-01
  • 2017-06-29
相关资源
最近更新 更多