|
| 1 | +object Meta: |
| 2 | + type Shape = String | Tuple |
| 3 | + |
| 4 | + type Demote[S <: Tuple]<: Shape = S match |
| 5 | + case Tuple1[t] => t & Shape |
| 6 | + case Tuple => S |
| 7 | + |
| 8 | + type If[T <: Boolean, R1, R2] <: R1 | R2 = T match |
| 9 | + case true => R1 |
| 10 | + case false => R2 |
| 11 | + |
| 12 | + type Contains[T <: Tuple, X] <: Boolean = T match |
| 13 | + case X *: r => true |
| 14 | + case _ *: r => Contains[r, X] |
| 15 | + case _ => false |
| 16 | + |
| 17 | + type RemoveStrict[T <: Tuple, X] <: Tuple = T match |
| 18 | + case head *: tail => head match |
| 19 | + case X => tail |
| 20 | + case _ => head *: RemoveStrict[tail, X] |
| 21 | + |
| 22 | + type WithoutStrict[T <: Tuple, T2 <: Tuple] <: Tuple = T2 match |
| 23 | + case head *: tail => WithoutStrict[RemoveStrict[T, head], tail] |
| 24 | + case EmptyTuple => T |
| 25 | + |
| 26 | + /** Removes all elems from ToReplace and replaces the first replaced elem with replacement */ |
| 27 | + type ReplaceAllStrict[T <: Tuple, ToReplace <: Tuple, Replacement] <: Tuple = T match |
| 28 | + case head *: tail => |
| 29 | + If[Contains[ToReplace, head], |
| 30 | + Replacement *: WithoutStrict[tail, RemoveStrict[ToReplace, head]], |
| 31 | + head *: ReplaceAllStrict[tail, ToReplace, Replacement]] |
| 32 | + case EmptyTuple => T |
| 33 | + |
| 34 | + type Sub[S <: Tuple, ToReplace <: Tuple, Replacement <: String] = |
| 35 | + Demote[ReplaceAllStrict[S, ToReplace, Replacement]] |
| 36 | + |
| 37 | +object Foo: |
| 38 | + import Meta._ |
| 39 | + val _0: Sub["batch" *: EmptyTuple, Int *: EmptyTuple, "batch"] = "batch" |
| 40 | + val _1: Sub[("batch", "len"), ("batch", "len"), "batch"] = "batch" |
| 41 | + val _2a: ReplaceAllStrict[("batch", "len", "embed"), "batch" *: EmptyTuple, "b"] = ("b", "len", "embed") |
| 42 | + type S = ("batch", "len") |
| 43 | + type ToReplace = "batch" *: EmptyTuple |
| 44 | + type Replacement = "b" |
| 45 | + val _2b: ReplaceAllStrict[S, ToReplace, Replacement] = ("b", "len") // ok |
| 46 | + val _2c: Demote[ReplaceAllStrict[S, ToReplace, Replacement]] = ("b", "len") // ok |
| 47 | + val _2d: Sub[S, ToReplace, Replacement] = ("b", "len") // error, see below |
0 commit comments