传递和使用隐式函数而不定义它

Sam*_*mar 3 scala implicit

我没有在ev任何地方定义该功能.那么,下面的代码怎么工作呢?是否必须在范围内定义implicits才能使用它们?

def same[T, U](x: U)(implicit ev: U => T): T = {ev(x)}
same(2) // 2
Run Code Online (Sandbox Code Playgroud)

Tra*_*own 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)
Run Code Online (Sandbox Code Playgroud)

因此,ev通过设置Predef.$conforms,会给你的一个实例的隐式方法A <:< A的任何A,其中<:<延伸Function1.

这是一个线索.弄清楚其余部分需要考虑类型推断.当你调用时same(2),编译器会发现表达式2有类型Int,并推断出它UInt.接下来需要弄清楚什么T是,要做到这一点它从寻找隐函数Intx对某些类型x.

这就是$conforms它的用武之地.它是范围内唯一的这样的方法,所以编译器选择它,这意味着它ev是类型的Int => Int,T必须是Int,并且你已经完成了.