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
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 r1
s 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).