我认为spec 的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。