@@ -5,7 +5,7 @@ import compiletime.*
5
5
import compiletime .ops .int .*
6
6
7
7
/** Tuple of arbitrary arity */
8
- sealed trait Tuple extends Product {
8
+ sealed trait Tuple extends Product :
9
9
import Tuple .*
10
10
11
11
/** Create a copy of this tuple as an Array */
@@ -84,66 +84,90 @@ sealed trait Tuple extends Product {
84
84
inline def reverse [This >: this .type <: Tuple ]: Reverse [This ] =
85
85
runtime.Tuples .reverse(this ).asInstanceOf [Reverse [This ]]
86
86
87
- /** A tuple with the fields of this tuple in reversed order added in front of `acc` */
87
+ /** A tuple with the elements of this tuple in reversed order added in front of `acc` */
88
88
inline def reverseOnto [This >: this .type <: Tuple , Acc <: Tuple ](acc : Acc ): ReverseOnto [This , Acc ] =
89
89
(this .reverse ++ acc).asInstanceOf [ReverseOnto [This , Acc ]]
90
90
91
91
/** A tuple consisting of all elements of this tuple that have types
92
- * for which the given predicate `P` evaluates to truye.
92
+ * for which the given type level predicate `P` reduces to the literal
93
+ * constant `true`.
93
94
*/
94
95
inline def filter [This >: this .type <: Tuple , P [_] <: Boolean ]: Filter [This , P ] =
95
96
val toInclude = constValueTuple[IndicesWhere [This , P ]].toArray
96
97
val arr = new Array [Object ](toInclude.length)
97
98
for i <- 0 until toInclude.length do
98
99
arr(i) = this .productElement(toInclude(i).asInstanceOf [Int ]).asInstanceOf [Object ]
99
100
Tuple .fromArray(arr).asInstanceOf [Filter [This , P ]]
100
- }
101
101
102
- object Tuple {
102
+ object Tuple :
103
103
104
- /** Type of a tuple with an element appended */
105
- type Append [X <: Tuple , Y ] <: NonEmptyTuple = X match {
106
- case EmptyTuple => Y *: EmptyTuple
107
- case x *: xs => x *: Append [xs, Y ]
108
- }
104
+ /** The size of a tuple, represented as a literal constant subtype of Int */
105
+ type Size [X <: Tuple ] <: Int = X match
106
+ case EmptyTuple => 0
107
+ case x *: xs => S [Size [xs]]
108
+
109
+ /** The type of the element at position N in the tuple X */
110
+ type Elem [X <: Tuple , N <: Int ] = X match
111
+ case x *: xs =>
112
+ N match
113
+ case 0 => x
114
+ case S [n1] => Elem [xs, n1]
109
115
110
- /** Type of the head of a tuple */
111
- type Head [X <: NonEmptyTuple ] = X match {
116
+ /** The type of the first element of a tuple */
117
+ type Head [X <: NonEmptyTuple ] = X match
112
118
case x *: _ => x
113
- }
114
119
115
- /** Type of the initial part of the tuple without its last element */
116
- type Init [X <: Tuple ] <: Tuple = X match {
120
+ /** The type of the last element of a tuple */
121
+ type Last [X <: Tuple ] = X match
122
+ case x *: EmptyTuple => x
123
+ case _ *: xs => Last [xs]
124
+
125
+ /** The type of a tuple consisting of all elements of tuple X except the first one */
126
+ type Tail [X <: NonEmptyTuple ] <: Tuple = X match
127
+ case _ *: xs => xs
128
+
129
+ /** The type of the initial part of a tuple without its last element */
130
+ type Init [X <: Tuple ] <: Tuple = X match
117
131
case _ *: EmptyTuple => EmptyTuple
118
132
case x *: xs =>
119
133
x *: Init [xs]
120
- }
121
134
122
- /** Type of the tail of a tuple */
123
- type Tail [X <: NonEmptyTuple ] <: Tuple = X match {
124
- case _ *: xs => xs
135
+ /** The type of the tuple consisting of the first `N` elements of `X`,
136
+ * or all elements if `N` exceeds `Size[X]`.
137
+ */
138
+ type Take [X <: Tuple , N <: Int ] <: Tuple = N match
139
+ case 0 => EmptyTuple
140
+ case S [n1] => X match
141
+ case EmptyTuple => EmptyTuple
142
+ case x *: xs => x *: Take [xs, n1]
143
+
144
+ /** The type of the tuple consisting of all elements of `X` except the first `N` ones,
145
+ * or no elements if `N` exceeds `Size[X]`.
146
+ */
147
+ type Drop [X <: Tuple , N <: Int ] <: Tuple = N match {
148
+ case 0 => X
149
+ case S [n1] => X match {
150
+ case EmptyTuple => EmptyTuple
151
+ case x *: xs => Drop [xs, n1]
152
+ }
125
153
}
126
154
127
- /** Type of the last element of a tuple */
128
- type Last [X <: Tuple ] = X match {
129
- case x *: EmptyTuple => x
130
- case _ *: xs => Last [xs]
155
+ /** Type of a tuple with an element appended */
156
+ type Append [X <: Tuple , Y ] <: NonEmptyTuple = X match {
157
+ case EmptyTuple => Y *: EmptyTuple
158
+ case x *: xs => x *: Append [xs, Y ]
131
159
}
132
160
133
- /** Type of the concatenation of two tuples */
134
- type Concat [X <: Tuple , + Y <: Tuple ] <: Tuple = X match {
161
+ /** The pair type `(Take(X, N), Drop[X, N]). */
162
+ type Split [X <: Tuple , N <: Int ] = (Take [X , N ], Drop [X , N ])
163
+
164
+ /** Type of the concatenation of two tuples `X` and `Y` */
165
+ type Concat [X <: Tuple , + Y <: Tuple ] <: Tuple = X match
135
166
case EmptyTuple => Y
136
167
case x1 *: xs1 => x1 *: Concat [xs1, Y ]
137
- }
138
168
139
- /** Type of the element at position N in the tuple X */
140
- type Elem [X <: Tuple , N <: Int ] = X match {
141
- case x *: xs =>
142
- N match {
143
- case 0 => x
144
- case S [n1] => Elem [xs, n1]
145
- }
146
- }
169
+ /** An infix shorthand for `Concat[X, Y]` */
170
+ infix type ++ [X <: Tuple , + Y <: Tuple ] = Concat [X , Y ]
147
171
148
172
/** The index of `Y` in tuple `X` as a literal constant Int,
149
173
* or `Size[X]` if `Y` does not occur in `X`
@@ -153,31 +177,30 @@ object Tuple {
153
177
case x *: xs => S [IndexOf [xs, Y ]]
154
178
case EmptyTuple => 0
155
179
156
- /** Literal constant Int size of a tuple */
157
- type Size [X <: Tuple ] <: Int = X match {
158
- case EmptyTuple => 0
159
- case x *: xs => S [Size [xs]]
160
- }
161
-
162
180
/** Fold a tuple `(T1, ..., Tn)` into `F[T1, F[... F[Tn, Z]...]]]` */
163
181
type Fold [Tup <: Tuple , Z , F [_, _]] = Tup match
164
182
case EmptyTuple => Z
165
183
case h *: t => F [h, Fold [t, Z , F ]]
166
184
167
- /** Converts a tuple `(T1, ..., Tn)` to `(F[T1], ..., F[Tn])` */
168
- type Map [Tup <: Tuple , F [_ <: Union [Tup ]]] <: Tuple = Tup match {
185
+ /** The type of tuple `X` mapped with the type-level function `F`.
186
+ * If `X = (T1, ..., Ti)` then `Map[X, F] = `(F[T1], ..., F[Ti])`.
187
+ */
188
+ type Map [Tup <: Tuple , F [_ <: Union [Tup ]]] <: Tuple = Tup match
169
189
case EmptyTuple => EmptyTuple
170
190
case h *: t => F [h] *: Map [t, F ]
171
- }
172
191
173
- /** Converts a tuple `(T1, ..., Tn)` to a flattened `(..F[T1], ..., ..F[Tn])` */
174
- type FlatMap [Tup <: Tuple , F [_ <: Union [Tup ]] <: Tuple ] <: Tuple = Tup match {
192
+ /** The type of tuple `X` flat-mapped with the type-level function `F`.
193
+ * If `X = (T1, ..., Ti)` then `FlatMap[X, F] = `F[T1] ++ ... ++ F[Ti]`
194
+ */
195
+ type FlatMap [Tup <: Tuple , F [_ <: Union [Tup ]] <: Tuple ] <: Tuple = Tup match
175
196
case EmptyTuple => EmptyTuple
176
197
case h *: t => Concat [F [h], FlatMap [t, F ]]
177
- }
198
+ // TODO: implement term level analogue
178
199
179
- /** Filters out those members of the tuple for which the predicate `P` returns `false`.
180
- * A predicate `P[X]` is a type that can be either `true` or `false`. For example:
200
+ /** The type of the tuple consisting of all elements of tuple `X` that have types
201
+ * for which the given type level predicate `P` reduces to the literal
202
+ * constant `true`. A predicate `P[X]` is a type that can be either `true`
203
+ * or `false`. For example:
181
204
* ```scala
182
205
* type IsString[x] <: Boolean = x match {
183
206
* case String => true
@@ -187,31 +210,38 @@ object Tuple {
187
210
* ```
188
211
* @syntax markdown
189
212
*/
190
- type Filter [Tup <: Tuple , P [_] <: Boolean ] <: Tuple = Tup match {
213
+ type Filter [X <: Tuple , P [_] <: Boolean ] <: Tuple = X match
191
214
case EmptyTuple => EmptyTuple
192
- case h *: t => P [h] match {
215
+ case h *: t => P [h] match
193
216
case true => h *: Filter [t, P ]
194
217
case false => Filter [t, P ]
195
- }
196
- }
197
218
198
219
/** A tuple consisting of those indices `N` of tuple `X` where the predicate `P`
199
220
* is true for `Elem[X, N]`. Indices are type level values <: Int.
200
221
*/
201
222
type IndicesWhere [X <: Tuple , P [_] <: Boolean ] =
202
223
helpers.IndicesWhereHelper [X , P , 0 ]
203
224
204
- /** Given two tuples, `A1 *: ... *: An * At` and `B1 *: ... *: Bn *: Bt`
205
- * where at least one of `At` or `Bt` is `EmptyTuple` or `Tuple`,
206
- * returns the tuple type `(A1, B1) *: ... *: (An, Bn) *: Ct`
207
- * where `Ct` is `EmptyTuple` if `At` or `Bt` is `EmptyTuple`, otherwise `Ct` is `Tuple`.
225
+ /** The type of the tuple consisting of all element values of
226
+ * tuple `X` zipped with corresponding elements of tuple `Y`.
227
+ * If the two tuples have different sizes,
228
+ * the extra elements of the larger tuple will be disregarded.
229
+ * For example, if
230
+ * ```
231
+ * X = (S1, ..., Si)
232
+ * Y = (T1, ..., Tj) where j >= i
233
+ * ```
234
+ * then
235
+ * ```
236
+ * Zip[X, Y] = ((S1, T1), ..., (Si, Ti))
237
+ * ```
238
+ * @syntax markdown
208
239
*/
209
- type Zip [T1 <: Tuple , T2 <: Tuple ] <: Tuple = (T1 , T2 ) match {
240
+ type Zip [T1 <: Tuple , T2 <: Tuple ] <: Tuple = (T1 , T2 ) match
210
241
case (h1 *: t1, h2 *: t2) => (h1, h2) *: Zip [t1, t2]
211
242
case (EmptyTuple , _) => EmptyTuple
212
243
case (_, EmptyTuple ) => EmptyTuple
213
244
case _ => Tuple
214
- }
215
245
216
246
/** Converts a tuple `(F[T1], ..., F[Tn])` to `(T1, ... Tn)` */
217
247
type InverseMap [X <: Tuple , F [_]] <: Tuple = X match {
@@ -226,36 +256,15 @@ object Tuple {
226
256
*/
227
257
type IsMappedBy [F [_]] = [X <: Tuple ] =>> X =:= Map [InverseMap [X , F ], F ]
228
258
229
- /** A tuple with the fields of tuple `X` in reversed order */
259
+ /** A tuple with the elements of tuple `X` in reversed order */
230
260
type Reverse [X <: Tuple ] = ReverseOnto [X , EmptyTuple ]
231
261
232
- /** A tuple with the fields of tuple `X` in reversed order added in front of `Acc` */
262
+ /** A tuple with the elements of tuple `X` in reversed order added in front of `Acc` */
233
263
type ReverseOnto [X <: Tuple , Acc <: Tuple ] <: Tuple = X match
234
264
case x *: xs => ReverseOnto [xs, x *: Acc ]
235
265
case EmptyTuple => Acc
236
266
237
- /** Transforms a tuple `(T1, ..., Tn)` into `(T1, ..., Ti)`. */
238
- type Take [T <: Tuple , N <: Int ] <: Tuple = N match {
239
- case 0 => EmptyTuple
240
- case S [n1] => T match {
241
- case EmptyTuple => EmptyTuple
242
- case x *: xs => x *: Take [xs, n1]
243
- }
244
- }
245
-
246
- /** Transforms a tuple `(T1, ..., Tn)` into `(Ti+1, ..., Tn)`. */
247
- type Drop [T <: Tuple , N <: Int ] <: Tuple = N match {
248
- case 0 => T
249
- case S [n1] => T match {
250
- case EmptyTuple => EmptyTuple
251
- case x *: xs => Drop [xs, n1]
252
- }
253
- }
254
267
255
- /** Splits a tuple (T1, ..., Tn) into a pair of two tuples `(T1, ..., Ti)` and
256
- * `(Ti+1, ..., Tn)`.
257
- */
258
- type Split [T <: Tuple , N <: Int ] = (Take [T , N ], Drop [T , N ])
259
268
260
269
/** Given a tuple `(T1, ..., Tn)`, returns a union of its
261
270
* member types: `T1 | ... | Tn`. Returns `Nothing` if the tuple is empty.
@@ -377,7 +386,7 @@ object Tuple {
377
386
case false => IndicesWhereHelper [t, P , S [N ]]
378
387
379
388
end helpers
380
- }
389
+ end Tuple
381
390
382
391
/** A tuple of 0 elements */
383
392
type EmptyTuple = EmptyTuple .type
0 commit comments