Samar
Samar

Reputation: 2101

passing & using an implicit function without defining it

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

Answers (1)

Travis Brown
Travis Brown

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

Related Questions