为什么没有找到隐式视图,当eta转换和指定类型参数确实允许找到隐式视图时?

Mat*_*ick 3 scala implicit

代码:

object Test {
  import scala.language.implicitConversions

  case class C1() {}
  case class C2() {}

  implicit def c1ToC2(in: C1): C2 = C2()

  def from[A, B](in: A)(implicit f: A => B): B = f(in)

  def fails(): Future[C2] = {
    val future: Future[C1] = Future.successful(C1())
    future.map(from) // this line fails to compile!
  }

  def compiles1(): Future[C2] = {
    val future: Future[C1] = Future.successful(C1())
    future.map(x => from(x))
  }

  def compiles2(): Future[C2] = {
    val future: Future[C1] = Future.successful(C1())
    future.map(from[C1, C2])
  }
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,只有该fails方法无法编译.错误消息是:

错误:(23,16)A => B. future.map(from)没有可用的隐式视图

我很困惑为什么没有发现隐式视图.基于该compiles1compiles2方法,其中两个编译成功,似乎还有得自A => B.一个隐含的视图

这里发生了什么,为什么这两种compilesN方法有效,但fails不是?

我的背景:我还在学习Scala,所以很容易就会发现我错过了很明显的东西.:)

我在使用Scala 2.11.8.

Mic*_*jac 6

编译器尝试在eta扩展from到函数之前解析implicits ,因此from当您调用它时,类型参数尚未推断:

future.map(from)
Run Code Online (Sandbox Code Playgroud)

compiles2显然有效,因为您自己提供类型参数.当你调用时future.map(from[C1, C2]),编译器知道它需要一个隐式的C1 => C2,因为这就是你所说的.

随着compiles1,不同的是多了几分微妙的,但它的事实,茎future.map(from)future.map(x => from(x))实际上是非常不同的事情.前者使用eta扩展,由于上述原因而失败.有future.map(x => from(x)),没有发生eta扩张.相反,你有一个匿名函数,只需调用 from而不是eta扩展它.因此,编译器可以推断出类型x,它告诉我们x是一个C1(在这种情况下),它可以找到c1ToC2满足方法from的隐式和最终返回类型的类型参数的隐式转换,Future[C2].