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

时间:2016-04-03 17:51:41

标签: scala types implicits implicit-typing

假设我有一个像这样的简单类

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中的值StringCanBuildFrom类型=> scala.collection.generic.CanBuildFrom [String,Char,String]和方法$ conforms in object Predef of type [A] => <:< [A,A]匹配预期类型A

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

val f2: Int = f[Int]()

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

请注意,如果我们删除Int并仅保留Ordering隐含参数,则错误仍然存​​在,但会变为

  

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

再次添加类型参数,使其变为implicit a: A有帮助。

发生了什么事?为什么编译器可以推断参数val f2: Int = f[Int]()必须是A,但参数Int必须不是Ordering[A]

1 个答案:

答案 0 :(得分: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()
}