从返回类型中推断通用隐式参数的类型

slo*_*ouc 7 types scala implicit-typing implicits

说我有一个像这样的简单类

abstract class Foo {
  implicit val impInt: Int = 42
  def f[A]()(implicit a: A): A
  val f2: Int = f()
}
Run Code Online (Sandbox Code Playgroud)

当声明VAL f2,编译器能够推断出的功能隐式参数的类型f是Int因为该类型是相同的结果类型,和结果类型需要匹配的值的类型f2,这是Int.

然而,投入Ordering[A]混合:

def f[A]()(implicit a: A, m: Ordering[A]): A
val f2: Int = f()
Run Code Online (Sandbox Code Playgroud)

导致此编译错误:

不明确的隐含值:对象的类型为StringCanBuildFrom,类型=> scala.collection.generic.CanBuildFrom [String,Char,String]的对象Predef和方法$ conforms对象Predef的类型为[A] => <:<[A,A]匹配预期类型A.

如果我在调用时添加类型信息f(),它会编译:

val f2: Int = f[Int]()
Run Code Online (Sandbox Code Playgroud)

首先我遇到了隐式排序的情况,我认为它与Scala从左到右推断有关; 我认为它首先不能匹配返回类型然后推断(隐式)参数类型f.但后来我尝试了没有隐式排序的情况,看到它有效 - 它推断f必须参数化,Int因为返回类型必须是Int(因为f2是Int).

请注意,如果我们删除implicit a: A并仅保留Ordering隐式参数,则错误仍然存​​在,但变为

在对象排序中从方法Tuple9开始,为类型排序[A]分散隐式扩展.

再次,添加类型参数,以便它变得有val f2: Int = f[Int]()帮助.

这是怎么回事?为什么编译器可以推断出参数A必须是a Int,但不是那个参数Ordering[A]必须是Ordering[Int]?

Edu*_*bes 1

生成排序实例的方式肯定有问题,因为下面的代码有效。我会报告一个错误。

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()
}
Run Code Online (Sandbox Code Playgroud)