简体   繁体   中英

Why does this Scala implicit conversion fail when explicit conversion works?

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: C <:< Iterable[A]) = new { def bar = 0 } 
view: [A, C](xs: C)(implicit ev: <:<[C,scala.collection.immutable.Iterable[A]])java.lang.Object{def bar: Int}

scala> List(1) bar
<console>:147: error: Cannot prove that List[Int] <:< scala.collection.immutable.Iterable[A].
              List(1) bar
                  ^

scala> view(List(1)) bar
res37: Int = 0

I'm not really answering your question (ie, 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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM