我认为规范的6.26.4局部类型推断部分解释了发生了什么。编译器将寻找最佳类型。当类型参数是逆变的时,选择的类型将是最大的(在这种情况下是 Any),否则(不变或协变)是最小的(在这种情况下是 Int)。
有几个我无法真正理解的例子reduceLeft
。
我注意到的是,在查看传递的匿名函数之前,推理似乎发生了:
scala> List(1,2).reduceLeft[Any](_.toString + _)
res26: Any = 12
但如果我不帮助类型推断器:
scala> List(1,2).reduceLeft(_.toString + _)
<console>:8: error: type mismatch;
found : java.lang.String
required: Int
List(1,2).reduceLeft(_.toString + _)
编辑,我错了,考虑到匿名函数,这有效:
List(1,2).reduceLeft((_:Any).toString + (_:Any).toString)
有一个-Ytyper-debug
可以运行的编译器选项:
List(1,2).reduceLeft(_+_)
它会告诉你编译器以某种方式假定匿名函数的预期类型是(Int, Int) => Int
,然后它继续检查_ + _
它并成功,然后推断B
为Int
。此处摘录:
typed immutable.this.List.apply[Int](1, 2).reduceLeft: [B >: Int](f: (B, Int) => B)B
adapted immutable.this.List.apply[Int](1, 2).reduceLeft: [B >: Int](f: (B, Int) => B)B to ?, undetparams=type B
typing ((x$1, x$2) => x$1.$plus(x$2)): pt = (Int, Int) => Int: undetparams=,
// some time later
typed ((x$1: Int, x$2: Int) => x$1.+(x$2)): (Int, Int) => Int
adapted ((x$1: Int, x$2: Int) => x$1.+(x$2)): (Int, Int) => Int to (Int, Int) => Int,
typed immutable.this.List.apply[Int](1, 2).reduceLeft[Int](((x$1: Int, x$2: Int) => x$1.+(x$2))): Int
我不知道为什么在没有类型归属的情况下假定匿名函数是(Int, Int) => Int
.