Why doesn\'t the following implicit conversion work even though explicitly calling the function works?
scala> implicit def view[A, C](xs: C)(implicit ev:
Simply put, as the error message suggests, it cannot infer A
. There's no information the compiler can use to infer what A
must be, so it must assume it can be anything.
You might retort that it can infer A
from C <:< Iterable[A]
, but that would turn the problem on its head: instead of using <:<
to check constraints, it would use the constraints to infer the type of A
! That logic is not sound.
I'm not really answering your question (i.e., I'm answering to "how do I make this work" but not to the "why does it not work"); anyway hopefully this will help someone else make some progress towards an answer.
So... In the first case, the compiler can't infer correctly that A is an Int, given that C is a List[Int]. Honestly I'm more surprised that passing the List explicitly actually works, since the relationship between A and C is so indirect (you have a A and a C, since C is a subtype of Iterable[A] and since C is a List[Int], then A must be an Int; not a very straightforward inference...).
You can make it work by being more explicit about the relationship between C and A, like this:
scala> implicit def view[A, C[A]](xs: C[A])(implicit ev: C[A] <:< Iterable[A]) =
new { def bar = 0 }
view: [A, C[A]](xs: C[A])(implicit ev: <:<[C[A],Iterable[A]])java.lang.Object{def bar: Int}
scala> List(1) bar
res0: Int = 0
or (given that you're not using A):
scala> implicit def view[C](xs: C)(implicit ev: C <:< Iterable[_]) =
new { def bar = 0 }
scala> List(1) bar
res1: Int = 0