Matt Fenwick Matt Fenwick - 2 months ago 8
Scala Question

Why is no implicit view found, when eta conversion and specifying type parameters does allow an implicit view to be found?

The code:

object Test {
import scala.language.implicitConversions

case class C1() {}
case class C2() {}

implicit def c1ToC2(in: C1): C2 = C2()

def from[A, B](in: A)(implicit f: A => B): B = f(in)

def fails(): Future[C2] = {
val future: Future[C1] = Future.successful(C1()) // this line fails to compile!

def compiles1(): Future[C2] = {
val future: Future[C1] = Future.successful(C1()) => from(x))

def compiles2(): Future[C2] = {
val future: Future[C1] = Future.successful(C1())[C1, C2])

In this example, only the
method fails to compile. The error message is:

Error:(23, 16) No implicit view available from A => B.

I'm confused about why no implicit view is found. Based on the
methods, which both successfully compile, it seems there is an implicit view available from A => B.

What is going on here, and why do the two
methods work, but
does not?

My background: I'm still learning Scala, so it could easily be the case that I'm missing something pretty obvious. :)

I'm on Scala 2.11.8.


The compiler attempts to resolve implicits before eta-expansion of from into a function, so the type parameters of from are not yet inferred when you call it like this:

compiles2 obviously works because you supply the type parameters on your own. When you call[C1, C2]), the compiler knows it will need an implicit C1 => C2, because that's what you've told it.

With compiles1, the difference is a little more subtle, but it stems from the fact that and => from(x)) are actually very different things. The former uses eta-expansion, which fails for the aforementioned reasons. With => from(x)), there is no eta-expansion happening. Instead, you have an anonymous function that simply calls from instead of eta-expanding it. Therefore, the compiler can infer the type of x, which tells us that x is a C1 (in this case), and it can find the implicit conversion c1ToC2 that satisfies the type parameters of from while resolving the implicit and the final return type of the method, Future[C2].