|
| 1 | +import scala.annotation.unchecked.uncheckedVariance |
| 2 | + |
| 3 | +import scala.language.implicitConversions |
| 4 | + |
| 5 | +sealed trait HList extends Product with Serializable |
| 6 | +final case class ::[+H, +T <: HList](head: H, tail: T) extends HList |
| 7 | + |
| 8 | +sealed trait HNil extends HList |
| 9 | +case object HNil extends HNil |
| 10 | + |
| 11 | +trait HListable[T] { |
| 12 | + type Out <: HList |
| 13 | +} |
| 14 | + |
| 15 | +object HListable { |
| 16 | + type HL0[T] <: HList = T match { |
| 17 | + case Unit => HNil |
| 18 | + case HNil => HNil |
| 19 | + case ::[a, b] => ::[a, b] |
| 20 | + case _ => T :: HNil |
| 21 | + } |
| 22 | + |
| 23 | + implicit def calc[T]: HListable[T] { type Out = HL0[T] } = ??? |
| 24 | +} |
| 25 | + |
| 26 | +sealed trait TailSwitch[L <: HList, T <: HList, R <: HList] { |
| 27 | + type Out <: HList |
| 28 | +} |
| 29 | +object TailSwitch { |
| 30 | + type Reverse0[Acc <: HList, L <: HList] <: HList = L match { |
| 31 | + case HNil => Acc |
| 32 | + case ::[h, t] => Reverse0[h :: Acc, t] |
| 33 | + } |
| 34 | + |
| 35 | + type Reverse1[L <: HList] <: HList = L match { |
| 36 | + case HNil => HNil |
| 37 | + case ::[h, t] => Reverse0[h :: HNil, t] |
| 38 | + } |
| 39 | + |
| 40 | + type Prepend0[A <: HList, B <: HList] <: HList = A match { |
| 41 | + case HNil => B |
| 42 | + case ::[h, t] => ::[h, Prepend0[t, B]] |
| 43 | + } |
| 44 | + |
| 45 | + // type-level implementation of this algorithm: |
| 46 | + // @tailrec def rec(L, LI, T, TI, R, RI) = |
| 47 | + // if (TI <: L) R |
| 48 | + // else if (LI <: T) RI.reverse ::: R |
| 49 | + // else if (LI <: HNil) rec(L, HNil, T, TI.tail, R, RI) |
| 50 | + // else if (TI <: HNil) rec(L, LI.tail, T, HNil, R, LI.head :: RI) |
| 51 | + // else rec(L, LI.tail, T, TI.tail, R, LI.head :: RI) |
| 52 | + // rec(L, L, T, T, R, HNil) |
| 53 | + type TailSwitch0[L <: HList, LI <: HList, T <: HList, TI <: HList, R <: HList, RI <: HList] <: HList = TI match { |
| 54 | + case L => R |
| 55 | + case _ => |
| 56 | + LI match { |
| 57 | + case T => Prepend0[Reverse1[RI], R] |
| 58 | + case HNil => |
| 59 | + TI match { |
| 60 | + case ::[_, t] => TailSwitch0[L, HNil, T, t, R, RI] |
| 61 | + } |
| 62 | + case ::[h, t] => |
| 63 | + TI match { |
| 64 | + case HNil => TailSwitch0[L, t, T, HNil, R, h :: RI] |
| 65 | + case ::[_, tt] => TailSwitch0[L, t, T, tt, R, h :: RI] |
| 66 | + } |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + type Aux[L <: HList, LI <: HList, T <: HList, TI <: HList, R <: HList, RI <: HList, Out <: HList] = |
| 71 | + TailSwitch[L, T, R] { type Out = TailSwitch0[L, L, T, T, R, HNil] } |
| 72 | + |
| 73 | + implicit def tailSwitch[L <: HList, T <: HList, R <: HList] |
| 74 | + : TailSwitch[L, T, R] { type Out = TailSwitch0[L, L, T, T, R, HNil] } = ??? |
| 75 | +} |
| 76 | + |
| 77 | +sealed class Rule[-I <: HList, +O <: HList] { |
| 78 | + def ~[I2 <: HList, O2 <: HList](that: Rule[I2, O2])(implicit |
| 79 | + i: TailSwitch[I2, O@uncheckedVariance, I@uncheckedVariance], |
| 80 | + o: TailSwitch[O@uncheckedVariance, I2, O2] |
| 81 | + ): Rule[i.Out, o.Out] = ??? |
| 82 | + |
| 83 | +} |
| 84 | +object Rule { |
| 85 | + type Rule0 = Rule[HNil, HNil] |
| 86 | + type RuleN[+L <: HList] = Rule[HNil, L] |
| 87 | + |
| 88 | + def rule[I <: HList, O <: HList](r: Rule[I, O]): Rule[I, O] = ??? |
| 89 | + implicit def valueMap[T](m: Map[String, T])(implicit h: HListable[T]): RuleN[h.Out] = ??? |
| 90 | +} |
| 91 | + |
| 92 | +object Test { |
| 93 | + import Rule._ |
| 94 | + val colors: Map[String, Int] = Map("red" -> 1, "green" -> 2, "blue" -> 3) |
| 95 | + def EOI: Rule0= ??? |
| 96 | + val r = rule(colors ~ EOI) |
| 97 | +} |
0 commit comments