|
| 1 | +sealed trait NatT { type This <: NatT } |
| 2 | +case class Zero() extends NatT { |
| 3 | + type This = Zero |
| 4 | +} |
| 5 | +case class Succ[N <: NatT](n: N) extends NatT { |
| 6 | + type This = Succ[n.This] |
| 7 | +} |
| 8 | + |
| 9 | +trait IsLessThan[+M <: NatT, N <: NatT] |
| 10 | +object IsLessThan: |
| 11 | + given base[M <: NatT]: IsLessThan[M, Succ[M]]() |
| 12 | + given weakening[N <: NatT, M <: NatT] (using IsLessThan[N, M]): IsLessThan[N, Succ[M]]() |
| 13 | + given reduction[N <: NatT, M <: NatT] (using IsLessThan[Succ[N], Succ[M]]): IsLessThan[N, M]() |
| 14 | + |
| 15 | +sealed trait UniformTuple[Length <: NatT, T]: |
| 16 | + def apply[M <: NatT](m: M)(using IsLessThan[m.This, Length]): T |
| 17 | + |
| 18 | +case class Empty[T]() extends UniformTuple[Zero, T]: |
| 19 | + def apply[M <: NatT](m: M)(using IsLessThan[m.This, Zero]): T = throw new AssertionError("Uncallable") |
| 20 | + |
| 21 | +case class Cons[N <: NatT, T](head: T, tail: UniformTuple[N, T]) extends UniformTuple[Succ[N], T]: |
| 22 | + def apply[M <: NatT](m: M)(using proof: IsLessThan[m.This, Succ[N]]): T = m match |
| 23 | + case Zero() => head |
| 24 | + case m1: Succ[predM] => |
| 25 | + val proof1: IsLessThan[m1.This, Succ[N]] = proof |
| 26 | + |
| 27 | + val res0 = tail(m1.n)(using IsLessThan.reduction(using proof)) // error // limitation |
| 28 | + val res1 = tail(m1.n)(using IsLessThan.reduction(using proof1)) |
| 29 | + res1 |
0 commit comments