Scala view application puzzler

前端 未结 5 1644
粉色の甜心
粉色の甜心 2021-02-04 09:20

Say we have the following two traits:

trait Foo[A] { def howMany(xs: List[A]) = xs.size }
trait Bar

And an implicit conversion from the second

相关标签:
5条回答
  • 2021-02-04 09:56

    For everyone's reference, this could only be a bug. The way you know that is the error message:

    <console>:13: error: type mismatch;
     found   : List[Int]
     required: List[A]
    

    List[A] is not a real type - it is List applied to its own type parameter. That is not a type which can be required since it is not a type which can be expressed.

    [Edit - it's too early, who knows what I'm talking about. Ignore the above, but you can still follow the link.]

    The relevant ticket for this is https://issues.scala-lang.org/browse/SI-6472 .

    0 讨论(0)
  • 2021-02-04 09:59

    Your implicit conversion seems to be doing exactly what you told it to do.

    implicit def bar2foo[A](bar: Bar) = new Foo[A] {}
    

    Converts a Bar to a new Foo[A] object. So in turn

    scala> bar howMany stuff
    <console>:13: error: type mismatch;
     found   : List[Int]
     required: List[A]
                  bar howMany stuff
    

    It looks for an 'A' type.

    In order to make this work the way you want it to you (I think), instead of defining the view on the trait you can do it on the function.

    trait Foo { def howMany[A](xs: List[A]) = xs.size }
    trait Bar
    implicit def bar2foo[A](bar: Bar) = new Foo{}
    val bar = new Bar {}
    val stuff = List(1, 2, 3)
    

    then it should give you the result you desire.

    scala> bar howMany stuff
    res0: Int = 3
    

    or you can define the view on the implicit function

    trait Foo[A] { def howMany(xs: List[A]) = xs.size }
    trait Bar
    
    implicit def bar2foo[A](bar: Bar) = new Foo[Int] {}
    
    val bar = new Bar {}
    val stuff = List(1, 2, 3)
    

    Personally I think defining it on the function is cleaner.

    0 讨论(0)
  • 2021-02-04 10:04

    Replacing your Foo with this:

    trait Foo[_] { def howMany(xs: List[_]) = xs.size }

    It works, which also makes quite a lot more sense to me because your absolutly not interested in A.

    0 讨论(0)
  • 2021-02-04 10:04

    This, while ugly, appears to work:

    (bar: Foo[Int]) howMany stuff
    
    0 讨论(0)
  • 2021-02-04 10:06

    This seems like a bug so my answers are:

    1. search for a simliar bug reported against the Scala compiler and if not found, report a new bug https://issues.scala-lang.org/
    2. that part of the spec doesn't seem to matter in this case as it doesn't talk about type inference
    3. doesn't make any sense to me

    PS. In 2.8.1 your workaround of adding the dummy method to Bar doesn't make it compile.

    0 讨论(0)
提交回复
热议问题