我没有在任何地方定义函数ev
。那么,下面的代码怎么工作呢?不要将隐含的内容定义在某个范围内以供它们使用吗?
def same[T, U](x: U)(implicit ev: U => T): T = {ev(x)}
same(2) // 2
答案 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)
所以ev
由Predef.$conforms
提供,这是一种隐式方法,可为任何A <:< A
提供A
的实例,其中<:<
扩展{{} 1}}。
这就是一个线索。弄清楚其余部分需要考虑类型推断。当您调用Function1
时,编译器会发现表达式same(2)
的类型为2
,并且推断Int
为U
。接下来需要确定Int
是什么,为此,它会针对某些类型T
寻找从Int
到x
的隐式函数。
这是x
的用武之地。它是范围内唯一的此类方法,因此编译器选择它,这意味着$conforms
的类型为ev
且{ {1}}必须为Int => Int
,您已完成。