假设我有一个类似的简单类
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()
导致此编译错误:
不明确的隐式值:类型=>scala.collection.generic.CanBuildFrom[String,Char,String]的对象Predef中的值StringCanBuildFrom和方法$都符合类型[A]=><的对象Preef:<[A,A]与预期的A类匹配
如果我在调用f()
时添加类型信息,它会编译:
val f2: Int = f[Int]()
首先,我遇到了隐式排序的情况,我认为这与Scala从左到右的推理有关;我认为它无法首先匹配返回类型,然后推断f
的(隐式)参数类型。但后来我尝试了没有隐式排序的情况,发现它是有效的——它推断f
必须由Int
参数化,因为返回类型必须是Int
(因为f2
是Int
)。
注意,如果我们删除implicit a: A
并只保留Ordering隐式参数,则错误仍然存在,但变为
从对象Ordering中的方法Tuple9开始,类型Ordering[A]的发散隐式展开。
同样,添加类型参数使其成为val f2: Int = f[Int]()
会有所帮助。
怎么回事?为什么编译器可以推断出参数A
必须是Int
,而不能推断出参数Ordering[A]
必须是Ordering[Int]
?
正如下面的代码所示,生成排序实例的方式一定有问题。我会报告一个错误。
case object types {
implicit def buh[X]: List[X] = List()
}
abstract class Foo {
import types._
def f[A]()(implicit l: List[A]): A
val f2: Int = f()
}