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

Why is no implicit view found, when eta conversion and specifying type parameters does allow an implicit view to be found?

代码:

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])
  }
}

本例中只有fails方法编译失败。错误信息是:

Error:(23, 16) No implicit view available from A => B. future.map(from)

我很困惑为什么没有找到隐式视图。基于 compiles1compiles2 方法,它们都成功编译,似乎 从 A => B.

可用的隐式视图

这是怎么回事,为什么 compilesN 两种方法有效,而 fails 无效?

我的背景:我仍在学习 Scala,所以我很容易遗漏一些非常明显的东西。 :)

我正在使用 Scala 2.11.8。

编译器会在将 from 扩展为函数之前尝试解析隐式,因此当您这样调用它时 from 的类型参数尚未推断出来:

future.map(from)

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 的类型参数,同时解析方法的隐式和最终 return 类型 Future[C2].