5

在 Scala (2.10) 中,如果我要求 aList(1.0, 2)那么我得到 a List[Double],正如预期的那样。

但...

如果我要求 aMap(1.0 -> 'A', 2 -> 'B')我得到一个Map[AnyVal, Char]. 我希望钥匙是 type Double。要求Map[Double, Char](1.0 -> 'A', 2 -> 'B)在“2”上给出类型不匹配。

这是我最困惑的!不矛盾吗?

旁白: List[(Double, Char)]((1.0, 'A'), (2, 'B')).toMap虽然给了我一个 Map[Double, Char] 。

4

2 回答 2

6

如果您查看 Scala 的类型层次结构,您会发现原始类型不在子类型/超类型关系中。Double但是,有一种称为数字扩展的机制,例如,它允许您通过传入 say来调用带有参数的方法Int。然后Int自动“扩大”到Double.

这就是List(1.0, 2)给你的原因List[Double]

但是Map构造函数需要Tuple[A, B]参数。数值扩展不适用于高阶类型,因此如果混合数值类型,目标类型推断对您不起作用。

case class Test[A](tup: (A, Char)*)
Test(1.0 -> 'A', 2 -> 'B') // AnyVal

此外,箭头运算符->会妨碍您:

Test[Double](2 -> 'B') // found: (Int, Char)  required: (Double, Char)

这是我认为类型推断的另一个限制。编写元组a -> b是 的语法糖(a, b),由 on 的隐式方法any2ArrowAssoc提供Predef。如果没有这种间接,如果你Tuple2直接构造,它可以工作:

Test[Double]((2, 'B'))

所以数字扩大仍然不起作用,但至少你可以强制类型:

Map[Double, Char]((1.0, 'A'), (2, 'B'))

最后一个例子展示了数值扩展的工作:

def map[A, B](keys: A*)(values: B*) = Map((keys zip values): _*)
map(1.0, 2)('A', 'B') // Map[Double, Char]
于 2013-01-19T17:50:31.223 回答
3

在 List 的情况下,没有类型声明,Scala 会查看所有元素并尝试找到公共类型。在您的情况下,由于 Int 可以转换为 Double,它将您的混合 List 转换为 List[Double] 提升您的一个 Int。

Map 构造函数采用一系列 2 元组。如果您只是构建了一个元组列表,您将得到相同的行为:

scala> List((1, "one"), (2.0, "two.oh"))
res0: List[(AnyVal, String)] = List((1,one), (2.0,two.oh))

Tuple2[Int, String] 不能自动提升为 Tuple2[Double, String]。在这种情况下,您需要通过类型声明帮助编译器:

scala> val x: List[(Double, String)] = List((1, "one"), (2.0, "two.oh"))
x: List[(Double, String)] = List((1.0,one), (2.0,two.oh))

或者

scala> val x = List[(Double, String)]((1, "one"), (2.0, "two.oh"))
x: List[(Double, String)] = List((1.0,one), (2.0,two.oh))

或者在你的情况下:

scala> val x = List[(Double, String)]((1, "one"), (2.0, "two.oh")).toMap
x: scala.collection.immutable.Map[Double,String] = Map(1.0 -> one, 2.0 -> two.oh)

由于某种原因,在 Map 上使用类型声明不起作用。不知道为什么:

scala> val x = Map[Double, String](1 -> "one", 2.0 -> "two.oh")
<console>:7: error: type mismatch;
found   : (Int, String)
required: (Double, String)
   val x = Map[Double, String](1 -> "one", 2.0 -> "two.oh")
于 2013-01-19T17:46:50.217 回答