Implicit Resolution Failure?

后端 未结 1 1016
孤城傲影
孤城傲影 2020-12-31 22:19

I have been working on a \"shapeless style\" implementation of Okasaki\'s dense binary number system. It\'s simply a type-level linked-list of bits; a sort of HList

相关标签:
1条回答
  • 2020-12-31 22:51

    This is a somewhat incomplete answer, but hopefully it'll get you unstuck ...

    I think your problem is the definition of r1 here,

    object Induction{
      def apply[A <: Dense](a: A)(implicit r: Induction[A]) = r
      implicit val r0 = new Induction[_0] {}
      implicit def r1[A <: Dense](implicit r: Induction[A], s: Succ[A]) = 
        new Induction[s.Out]{}
    }
    

    When you ask for Induction(_2) you're hoping for r1 to be applicable and s.Out to be fixed as _2 and that that will drive the inference process from right to left in r1s implicit parameter block.

    Unfortunately that won't happen. First, s.Out won't be fixed as _2 because it isn't a type variable. So you would at the very least have to rewrite this as,

    implicit def r1[A <: Dense, SO <: Dense]
      (implicit r: Induction[A], s: Succ.Aux[A, SO]): Induction[SO] = 
        new Induction[SO]{}
    

    for r1 even to be applicable. This won't get you much further, however, because SO is merely constrained to be equal to the type member Out of s ... it doesn't play a role in the selection of the Succ instance for s. And we can't make any progress from the other end, because at this point A is completely undetermined as far as the typechecker is concerned.

    So I'm afraid you'll have to rethink this a little. I think your best approach would be to define a Pred operator which would allow you to define something along these lines,

    implicit def r1[S <: Dense, PO <: Dense]
      (implicit p: Pred.Aux[S, PO], r: Induction[PO]): Induction[S] = 
        new Induction[S]{}
    

    Now when you ask for Induction(_2) S will be solved immediately as _2, the Pred instance for _2 will be resolved, yielding a solution of _1 for PO which gives the typechecker what it needs to resolve the next step of the induction.

    Notice that the general strategy is to start with the result type (Induction[S]) to fix the initial type variable(s), and then work from left to right across the implicit parameter list.

    Also notice that I've added explicit result types to the implicit definitions: you should almost always do this (there are rare exceptions to this rule).

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