7

说我有一个像这样的简单课程

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

在声明 val 时f2,编译器能够推断出函数隐式参数的类型fInt因为该类型与结果类型相同,结果类型需要与 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]

4

1 回答 1

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()
}
于 2016-11-15T12:12:28.217 回答