|
| 1 | +object NatsVects { |
| 2 | + sealed trait TNat |
| 3 | + case class TZero() extends TNat |
| 4 | + case class TSucc[N <: TNat] extends TNat |
| 5 | + |
| 6 | + object TNatSum { |
| 7 | + sealed trait TSum[M, N, R] |
| 8 | + case class TSumZero[N]() extends TSum[TZero, N, N] |
| 9 | + case class TSumM[M <: TNat, N, R <: TNat](sum: TSum[M, N, R]) extends TSum[TSucc[M], N, TSucc[R]] |
| 10 | + } |
| 11 | + import TNatSum._ |
| 12 | + |
| 13 | + implicit def tSumZero[N]: TSum[TZero, N, N] = |
| 14 | + TSumZero() |
| 15 | + //new TSum[TZero, N, N]() {} |
| 16 | + implicit def tSumM[M <: TNat, N, R <: TNat](implicit sum: TSum[M, N, R]): TSum[TSucc[M], N, TSucc[R]] = |
| 17 | + TSumM(sum) |
| 18 | + //new TSum[TSucc[M], N, TSucc[R]] {} |
| 19 | + |
| 20 | + sealed trait Vec[+T, N <: TNat] |
| 21 | + case object VNil extends Vec[Nothing, TZero] // fails but in refchecks |
| 22 | + case class VCons[T, N <: TNat](x: T, xs: Vec[T, N]) extends Vec[T, TSucc[N]] |
| 23 | + |
| 24 | + implicit class vecOps[T, M <: TNat]($this: Vec[T, M]) extends AnyVal { |
| 25 | + def append[N <: TNat, R <: TNat](that: Vec[T, N])(implicit tsum: TSum[M, N, R]): Vec[T, R] = { |
| 26 | + // tsum match { |
| 27 | + // case _: TSumZero[N] => // Here N = R |
| 28 | + // $this match { |
| 29 | + // case VNil => |
| 30 | + // //that |
| 31 | + // that.asInstanceOf[Vec[T, R]] |
| 32 | + // case VCons(x, xs) => |
| 33 | + // ??? |
| 34 | + // } |
| 35 | + // case TSumM(sum) => |
| 36 | + // ??? |
| 37 | + // } |
| 38 | + $this match { |
| 39 | + case VNil => // M = TZero |
| 40 | + tsum match { |
| 41 | + case TSumZero() => that |
| 42 | + //* case _: TSumZero[TZero] => |
| 43 | + //* that |
| 44 | + //* // that.asInstanceOf[Vec[T, R]] |
| 45 | + case _: TSumM[_, _, _] => // Impossible, this forces M = TSucc[M1] |
| 46 | + ??? |
| 47 | + } |
| 48 | + //* case vxs: VCons[T, m1] => // M = TSucc[m1], xs: Vec[T, m1] |
| 49 | + //* val x = vxs.x |
| 50 | + //* val xs = vxs.xs |
| 51 | + //* //case VCons(x, xs) => |
| 52 | + //* tsum match { |
| 53 | + //* case _: TSumZero[TZero] => // impossible, since this forces M = TZero. |
| 54 | + //* ??? |
| 55 | + //* // fails |
| 56 | + //* // case tsum1: TSumM[`m1`, n, r] => // M = TSucc[m1], R = TSucc[r] |
| 57 | + //* // implicit val tsum2 = tsum1.sum |
| 58 | + //* // val appended = xs append that |
| 59 | + //* // VCons(x, appended) // Vec[T, TSucc[r]] |
| 60 | + //* //works |
| 61 | + //* case tsum1: TSumM[`m1`, N, r] => // M = TSucc[m1], R = TSucc[r] |
| 62 | + //* implicit val tsum2 = tsum1.sum |
| 63 | + //* // I should be able to return: |
| 64 | + //* VCons(x, xs append that) // Vec[T, TSucc[r]] = Vec[T, R] |
| 65 | + |
| 66 | + //* // val vxs1 = xs append that |
| 67 | + //* // val vxs2 = VCons(x, vxs1) |
| 68 | + //* // vxs1 |
| 69 | + //* // [error] -- [E007] Type Mismatch Error: /Users/pgiarrusso/git/dotty-example-project/src/main/scala/playground/gadtVect.scala:65:14 |
| 70 | + //* // [error] 65 | vxs1 |
| 71 | + //* // [error] | ^^^^ |
| 72 | + //* // [error] | found: NatsVects.Vec[T, r](vxs1) |
| 73 | + //* // [error] | required: NatsVects.Vec[T, R] |
| 74 | + //* // [error] | |
| 75 | + //* // [error] | where: r is a type in method append with bounds <: NatsVects.TNat |
| 76 | + //* // vxs2 |
| 77 | + //* // [error] -- [E007] Type Mismatch Error: /Users/pgiarrusso/git/dotty-example-project/src/main/scala/playground/gadtVect.scala:71:14 |
| 78 | + //* // [error] 71 | vxs2 |
| 79 | + //* // [error] | ^^^^ |
| 80 | + //* // [error] | found: NatsVects.VCons[T, r](vxs2) |
| 81 | + //* // [error] | required: NatsVects.Vec[T, R] |
| 82 | + //* // [error] | |
| 83 | + //* // [error] | where: r is a type in method append with bounds <: NatsVects.TNat |
| 84 | + |
| 85 | + //* // vxs2.asInstanceOf // sorry this works |
| 86 | + //* } |
| 87 | + } |
| 88 | + } |
| 89 | + } |
| 90 | +} |
0 commit comments