当 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)
我很困惑为什么没有找到隐式视图。基于 compiles1
和 compiles2
方法,它们都成功编译,似乎 是 从 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]
.
代码:
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)
我很困惑为什么没有找到隐式视图。基于 compiles1
和 compiles2
方法,它们都成功编译,似乎 是 从 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]
.