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

后端 未结 2 1569
眼角桃花
眼角桃花 2021-01-14 02:51

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:          


        
相关标签:
2条回答
  • 2021-01-14 03:14

    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.

    0 讨论(0)
  • 2021-01-14 03:33

    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
    
    0 讨论(0)
提交回复
热议问题