Scala: Implicit evidence for class with type parameter

后端 未结 3 1551
清歌不尽
清歌不尽 2021-02-14 07:20

Here is a simple setup with two traits, a class with a covariant type parameter bounded by the previous traits, and a second class with a type parameter bounded by the other cla

3条回答
  •  我寻月下人不归
    2021-02-14 07:34

    The call bar.readField is possible because the evidence instance <:< allows an implicit conversion from B to Bar[ReadableFoo].

    The problem I think that to call readField you need a successive evidence parameter F <:< ReadableFoo. So my guess is, the compiler doesn't fully substitute the type parameter of Bar in the first search stage of the implicit resolution (because to find readField, it just requires any Bar in the first place). And then it chokes on the second implicit resolution, because there is no form of 'backtracking' as far as I know.

    Anyway. The good thing is, you know more than the compiler and you can engage the conversion explicitly, either by using the apply method of <:<, or by using the helper method implicitly:

    case class Grill[+B <: Bar[_]](bar: B) {
      def readField(implicit evidence: B <:< Bar[ReadableFoo]) = evidence(bar).readField
    }
    
    case class Grill[+B <: Bar[_]](bar: B) {
      def readField(implicit evidence: B <:< Bar[ReadableFoo]) = 
        implicitly[Bar[ReadableFoo]](bar).readField
    }
    

    There is another possibility which might be the cleanest, as it doesn't rely on the implementation of <:< which might be a problem as @Kaito suggests:

    case class Grill[+B <: Bar[_]](bar: B) {
      def readField(implicit evidence: B <:< Bar[ReadableFoo]) =
         (bar: Bar[ReadableFoo]).readField
    }
    

提交回复
热议问题