Pen*_*gin 5 scala type-inference
在Scala(2.10)中,如果我要求a,List(1.0, 2)那么我会得到一个List[Double],如预期的那样.
但...
如果我要求Map(1.0 -> 'A', 2 -> 'B')我得到一个Map[AnyVal, Char].我希望钥匙是类型的Double.要求Map[Double, Char](1.0 -> 'A', 2 -> 'B)在'2'上给出类型不匹配.
这让我觉得最让人困惑!它不一致吗?
旁白: List[(Double, Char)]((1.0, 'A'), (2, 'B')).toMap虽然给了我一张地图[Double,Char].
如果查看Scala的类型层次结构,可以看到基本类型不属于子类型/超类型关系.但是,有一种称为数字扩展的机制,例如,允许您Double通过传入一个参数来调用一个接受参数的方法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
Run Code Online (Sandbox Code Playgroud)
此外,箭头操作符->挡住了你的方式:
Test[Double](2 -> 'B') // found: (Int, Char) required: (Double, Char)
Run Code Online (Sandbox Code Playgroud)
这是我认为的类型推断的另一个限制.写一个元组a -> b是语法糖(a, b),由隐式方法any2ArrowAssoc提供Predef.没有这个间接,如果你Tuple2直接构造它,它的工作原理:
Test[Double]((2, 'B'))
Run Code Online (Sandbox Code Playgroud)
所以数字扩展仍然不起作用,但至少你可以强制执行类型:
Map[Double, Char]((1.0, 'A'), (2, 'B'))
Run Code Online (Sandbox Code Playgroud)
显示数字扩展工作的最后一个示例:
def map[A, B](keys: A*)(values: B*) = Map((keys zip values): _*)
map(1.0, 2)('A', 'B') // Map[Double, Char]
Run Code Online (Sandbox Code Playgroud)