说我有一个像这样的简单课程
abstract class Foo {
implicit val impInt: Int = 42
def f[A]()(implicit a: A): A
val f2: Int = f()
}
在声明 val 时f2
,编译器能够推断出函数隐式参数的类型f
是Int
因为该类型与结果类型相同,结果类型需要与 value 的类型相匹配f2
,即Int
.
然而,把一个Ordering[A]
混合在一起:
def f[A]()(implicit a: A, m: Ordering[A]): A
val f2: Int = f()
导致此编译错误:
模棱两可的隐含值:类型 => scala.collection.generic.CanBuildFrom[String,Char,String] 的对象 Predef 中的值 StringCanBuildFrom 和类型 [A]=> <:<[A,A] 的对象 Predef 中的方法 $conforms匹配预期类型 A
如果我在调用时添加类型信息f()
,它会编译:
val f2: Int = f[Int]()
首先,我遇到了隐式排序的情况,我认为这与 Scala 推断从左到右有关;我认为它无法先匹配返回类型,然后推断f
. 但是后来我在没有隐式排序的情况下尝试了这种情况,并看到它有效 - 它推断f
必须参数化,Int
因为返回类型必须是 an Int
(因为f2
是 an Int
)。
请注意,如果我们删除implicit a: A
并仅保留 Ordering 隐式参数,则错误仍然存在,但变为
从对象 Ordering 中的方法 Tuple9 开始的类型 Ordering[A] 的发散隐式扩展。
同样,添加类型参数使其变得有val f2: Int = f[Int]()
帮助。
这是怎么回事?为什么编译器可以推断该参数A
必须是一个Int
,但不能推断该参数Ordering[A]
必须是一个Ordering[Int]
?