假设我有一个简单的类如下:
abstract class Foo {
implicit val impInt: Int = 42
def f[A]()(implicit a: A): A
val f2: Int = f()
}
在声明val f2
时,编译器能够推断出函数f
的隐式参数类型为Int
,因为该类型与结果类型相同,而结果类型需要匹配值f2
的类型,即Int
。
然而,当涉及到抛出一个Ordering[A]
时:
def f[A]()(implicit a: A, m: Ordering[A]): A
val f2: Int = f()
在编译过程中出现以下错误:
模糊的隐式值:对象 Predef 中类型为 => scala.collection.generic.CanBuildFrom [String,Char,String] 的值 StringCanBuildFrom 和类型为 [A] => <:<[A,A] 的方法 $conforms 都与预期的类型 A 匹配
如果在调用 f()
时添加类型信息,则可编译通过:
val f2: Int = f[Int]()
首先,我遇到了隐式排序的情况,我认为这与Scala从左到右推断有关;我认为它无法首先匹配返回类型,然后再推断
f
的(隐式)参数类型。但是后来我尝试了没有隐式排序的情况,发现它可以工作-它推断出f
必须由Int
进行参数化,因为返回类型必须是一个Int
(因为f2
是一个Int
)。需要注意的是,如果我们移除
implicit a:A
并仅留下Ordering隐式参数,则错误仍然存在,但变成了“Diverging implicit expansion for type Ordering [A] starting with method Tuple9 in object Ordering.”同样地,添加类型参数使其变成
val f2:Int = f[Int]()
可以帮助解决问题。发生了什么?为什么编译器可以推断参数
A
必须是一个Int
,但不能推断参数Ordering [A]
必须是一个Ordering [Int]
?