0

I came up with the following per this problem:

enter image description here

package net

import shapeless.{::, HNil, _}
import ops.hlist.IsHCons
import nat._
import ops.nat.{Mod, Prod, Sum}

trait IsValid[A]
object IsValid {

  def apply[L <: HList](implicit ev: IsValid[L]) = ev

  //  account number:  3  4  5  8  8  2  8  6  5
  //  position names:  d9 d8 d7 d6 d5 d4 d3 d2 d1
  //
  //  checksum calculation:
  //    (d1+2*d2+3*d3 +..+9*d9) mod 11 = 0
  implicit def validNumber[D9 <: Nat, D8 <: Nat, D7 <: Nat, D6 <: Nat, D5 <: Nat, D4 <: Nat, D3 <: Nat, D2 <: Nat, D1 <: Nat,
                           P9 <: Nat, P8 <: Nat, P7 <: Nat, P6 <: Nat, P5 <: Nat, P4 <: Nat, P3 <: Nat, P2 <: Nat, P1 <: Nat,
                           S1 <: Nat, S2 <: Nat, S3 <: Nat, S4 <: Nat, S5 <: Nat, S6 <: Nat, S7 <: Nat, S8 <: Nat](
    implicit p9: Prod.Aux[D9, _9, P9],
    p8 : Prod.Aux[D8, _8, P8],
    p7 : Prod.Aux[D7, _7, P7],
    p6 : Prod.Aux[D6, _6, P6],
    p5 : Prod.Aux[D5, _5, P5],
    p4 : Prod.Aux[D4, _4, P4],
    p3 : Prod.Aux[D3, _3, P3],
    p2 : Prod.Aux[D2, _2, P2],
    p1 : Prod.Aux[D1, _1, P1],
    s1: Sum.Aux[P9, P8, S1],
    s2: Sum.Aux[P7, S1, S2],
    s3: Sum.Aux[P6, S2, S3],
    s4: Sum.Aux[P5, S3, S4],
    s5: Sum.Aux[P4, S4, S5],
    s6: Sum.Aux[P3, S5, S6],
    s7: Sum.Aux[P2, S6, S7],
    s8: Sum.Aux[P1, S7, S8],
    mod: Mod.Aux[S8, _11, _0]
  ): IsValid[D9 :: D8 :: D7 :: D6 :: D5 :: D4 :: D3 :: D2 :: D1 :: HNil] = {
    new IsValid[D9 :: D8 :: D7 :: D6 :: D5 :: D4 :: D3 :: D2 :: D1 :: HNil] {}
  }


}

It appears to work for the 0 case:

scala> import net.IsValid, shapeless._, nat._
import net.IsValid
import shapeless._
import nat._

scala> IsValid[_0 :: _0 :: _0 :: _0 :: _0 :: _0 :: _0 :: _0 :: _0 :: HNil]
res0: net.IsValid[shapeless.::...

But, when I call the following "valid" combination, the console shows no output, i.e. hangs.

scala> IsValid[_3 :: _4 :: _5 :: _8 :: _8 :: _2 :: _8 :: _6 :: _5 :: HNil]

I only waited ~2 minutes before asking this question.

I'm assuming that it's doing the implicit lookups, but I'm not sure.

Why does the above call hang? Perhaps there's an error in my code?

Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384
  • 2
    That's going to take a while to compile. A recursive version of this will most likely compile more quickly. FWIW, Travis Brown and Paul Snively have shapeless-based solutions for this problem. – Miles Sabin Feb 07 '17 at 15:07
  • Thanks, Miles. I am trying to come up with my own solution before peeking at their impressive work! Why does the 0 case compile so quickly? – Kevin Meredith Feb 07 '17 at 15:10
  • 1
    `Sum` is linear in the difference between the first and second `Nat` type arguments argument, and `Prod` is quadratic in the same. So you have the sum of eight linear and eight quadratic terms. `Mod` is also quadratic. Where these are all `_0` it's not going to take long, but otherwise it's nasty. My inductive implicits PR for 2.12.x should speed this up a lot. – Miles Sabin Feb 07 '17 at 18:11
  • I tried the new 2.12.1 Typelevel scala. But my code is still compiling after 12 hours. – Kevin Meredith Feb 10 '17 at 02:49
  • Did you add `-Yinduction-heuristics`? – Miles Sabin Feb 10 '17 at 17:07
  • Assuming I added the `scalac` flag [properly](https://github.com/kevinmeredith/KataBankOCR_shapeless/blob/master/build.sbt), I killed its compilation after ~12 hours - https://gist.github.com/kevinmeredith/40b132f0928bc6cf740c75a30cada02e. – Kevin Meredith Feb 16 '17 at 12:55

0 Answers0