Scala对集合的类型推断表现得很奇怪?

时间:2013-10-20 22:02:47

标签: scala type-inference scala-collections

看起来很奇怪,这不起作用:

scala> (1 to 6).toSet map (_ / 2)
<console>:8: error: missing parameter type for expanded function ((x$1) => x$1.$div(2))
              (1 to 6).toSet map (_ / 2)
                                  ^

但是,使用to[Set]代替toSet会:

scala> (1 to 6).to[Set] map (_ / 2)
res0: scala.collection.immutable.Set[Int] = Set(2, 0, 3, 1)

咦。 O_O

还要考虑这是有效的:

scala> val s = (1 to 6).toSet; s map (_ / 2)
s: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)
res1: scala.collection.immutable.Set[Int] = Set(2, 0, 3, 1)

由于Range.Inclusive是@AlexIv建议的一阶类型,请注意,这也不适用于List[Int]

scala> List(1, 2, 3, 4, 5, 6).toSet map (_ / 2)
<console>:8: error: missing parameter type for expanded function ((x$1) => x$1.$
div(2))
              List(1, 2, 3, 4, 5, 6).toSet map (_ / 2)
                                                ^

和以前一样,这有效:

scala> val s = List[Int](1, 2, 3, 4, 5, 6).toSet; s map (_ / 2)
s: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)
res3: scala.collection.immutable.Set[Int] = Set(2, 0, 3, 1)

修改Type inference fails on Set made with .toSet?

的副本

1 个答案:

答案 0 :(得分:1)

typer阶段(scala -Xprint:typer)隐藏了答案:

private[this] val res7: <error> = Predef.intWrapper(1).to(6).toSet[B].map[B, That]({
  ((x: Nothing) => Predef.identity[Nothing](x))
})();

(1 to 6)返回一个Range.Inclusive,它是一阶类型而不是一个类型构造函数,它没有参数化,但是Set[A]期望/要求你提供一些类型并返回给你一个类型。当您致电toSet时,scalac需要某种类型,因为Inclusive没有toSet方法,它继承自TraversableOnce并且是一种通用方法,所以您需要明确提供某种类型:

(1 to 6).toSet[Int].map(identity)
res0: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)

toBuffer也不起作用,其他转换效果很好,这两种方法也有类似的实现:

def toBuffer[B >: A]: mutable.Buffer[B] = to[ArrayBuffer].asInstanceOf[mutable.Buffer[B]]

def toSet[B >: A]: immutable.Set[B] = to[immutable.Set].asInstanceOf[immutable.Set[B]]