Reputation: 2101
I have not defined the function ev
anywhere. Then, how come the below code works? Don't implicits have to be defined somewhere in scope for them to be used?
def same[T, U](x: U)(implicit ev: U => T): T = {ev(x)}
same(2) // 2
Upvotes: 3
Views: 53
Reputation: 139058
Any time you have questions like this, a good place to start is by using the Scala reflection API in the REPL to ask the compiler what's going on:
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)
So ev
is provided by Predef.$conforms
, an implicit method that will give you an instance of A <:< A
for any A
, where <:<
extends Function1
.
So that's one clue. Figuring out the rest requires thinking a little about type inference. When you call same(2)
, the compiler figures out that the expression 2
has type Int
, and infers that U
is Int
. Next it needs to figure out what T
is, and to do that it goes looking for implicit functions from Int
to x
for some type x
.
This is where $conforms
comes in. It's the only such method in scope, so the compiler chooses it, which means that ev
is of type Int => Int
and T
has to be Int
, and you're done.
Upvotes: 5