传球&使用隐式函数而不定义它

时间:2016-10-09 14:21:15

标签: scala implicit

我没有在任何地方定义函数ev。那么,下面的代码怎么工作呢?不要将隐含的内容定义在某个范围内以供它们使用吗?

def same[T, U](x: U)(implicit ev: U => T): T = {ev(x)}
same(2) // 2

1 个答案:

答案 0 :(得分:5)

任何时候你有这样的问题,一个好的起点是使用REPL中的Scala反射API来询问编译器发生了什么:

scala> import scala.reflect.runtime.universe.{ reify, showCode }
import scala.reflect.runtime.universe.{reify, showCode}

scala> def same[T, U](x: U)(implicit ev: U => T): T = ev(x)
same: [T, U](x: U)(implicit ev: U => T)T

scala> showCode(reify(same(2)).tree)
res0: String = $read.same(2)(Predef.$conforms)

所以evPredef.$conforms提供,这是一种隐式方法,可为任何A <:< A提供A的实例,其中<:<扩展{{} 1}}。

这就是一个线索。弄清楚其余部分需要考虑类型推断。当您调用Function1时,编译器会发现表达式same(2)的类型为2,并且推断IntU。接下来需要确定Int是什么,为此,它会针对某些类型T寻找从Intx的隐式函数。

这是x的用武之地。它是范围内唯一的此类方法,因此编译器选择它,这意味着$conforms的类型为ev且{ {1}}必须为Int => Int,您已完成。