@@ -5,7 +5,7 @@ import compiletime.*
55import compiletime .ops .int .*
66
77/** Tuple of arbitrary arity */
8- sealed trait Tuple extends Product {
8+ sealed trait Tuple extends Product :
99 import Tuple .*
1010
1111 /** Create a copy of this tuple as an Array */
@@ -84,66 +84,90 @@ sealed trait Tuple extends Product {
8484 inline def reverse [This >: this .type <: Tuple ]: Reverse [This ] =
8585 runtime.Tuples .reverse(this ).asInstanceOf [Reverse [This ]]
8686
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` */
8888 inline def reverseOnto [This >: this .type <: Tuple , Acc <: Tuple ](acc : Acc ): ReverseOnto [This , Acc ] =
8989 (this .reverse ++ acc).asInstanceOf [ReverseOnto [This , Acc ]]
9090
9191 /** 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`.
9394 */
9495 inline def filter [This >: this .type <: Tuple , P [_] <: Boolean ]: Filter [This , P ] =
9596 val toInclude = constValueTuple[IndicesWhere [This , P ]].toArray
9697 val arr = new Array [Object ](toInclude.length)
9798 for i <- 0 until toInclude.length do
9899 arr(i) = this .productElement(toInclude(i).asInstanceOf [Int ]).asInstanceOf [Object ]
99100 Tuple .fromArray(arr).asInstanceOf [Filter [This , P ]]
100- }
101101
102- object Tuple {
102+ object Tuple :
103103
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]
109115
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
112118 case x *: _ => x
113- }
114119
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
117131 case _ *: EmptyTuple => EmptyTuple
118132 case x *: xs =>
119133 x *: Init [xs]
120- }
121134
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+ }
125153 }
126154
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 ]
131159 }
132160
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
135166 case EmptyTuple => Y
136167 case x1 *: xs1 => x1 *: Concat [xs1, Y ]
137- }
138168
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 ]
147171
148172 /** The index of `Y` in tuple `X` as a literal constant Int,
149173 * or `Size[X]` if `Y` does not occur in `X`
@@ -153,31 +177,30 @@ object Tuple {
153177 case x *: xs => S [IndexOf [xs, Y ]]
154178 case EmptyTuple => 0
155179
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-
162180 /** Fold a tuple `(T1, ..., Tn)` into `F[T1, F[... F[Tn, Z]...]]]` */
163181 type Fold [Tup <: Tuple , Z , F [_, _]] = Tup match
164182 case EmptyTuple => Z
165183 case h *: t => F [h, Fold [t, Z , F ]]
166184
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
169189 case EmptyTuple => EmptyTuple
170190 case h *: t => F [h] *: Map [t, F ]
171- }
172191
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
175196 case EmptyTuple => EmptyTuple
176197 case h *: t => Concat [F [h], FlatMap [t, F ]]
177- }
198+ // TODO: implement term level analogue
178199
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:
181204 * ```scala
182205 * type IsString[x] <: Boolean = x match {
183206 * case String => true
@@ -187,31 +210,38 @@ object Tuple {
187210 * ```
188211 * @syntax markdown
189212 */
190- type Filter [Tup <: Tuple , P [_] <: Boolean ] <: Tuple = Tup match {
213+ type Filter [X <: Tuple , P [_] <: Boolean ] <: Tuple = X match
191214 case EmptyTuple => EmptyTuple
192- case h *: t => P [h] match {
215+ case h *: t => P [h] match
193216 case true => h *: Filter [t, P ]
194217 case false => Filter [t, P ]
195- }
196- }
197218
198219 /** A tuple consisting of those indices `N` of tuple `X` where the predicate `P`
199220 * is true for `Elem[X, N]`. Indices are type level values <: Int.
200221 */
201222 type IndicesWhere [X <: Tuple , P [_] <: Boolean ] =
202223 helpers.IndicesWhereHelper [X , P , 0 ]
203224
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
208239 */
209- type Zip [T1 <: Tuple , T2 <: Tuple ] <: Tuple = (T1 , T2 ) match {
240+ type Zip [T1 <: Tuple , T2 <: Tuple ] <: Tuple = (T1 , T2 ) match
210241 case (h1 *: t1, h2 *: t2) => (h1, h2) *: Zip [t1, t2]
211242 case (EmptyTuple , _) => EmptyTuple
212243 case (_, EmptyTuple ) => EmptyTuple
213244 case _ => Tuple
214- }
215245
216246 /** Converts a tuple `(F[T1], ..., F[Tn])` to `(T1, ... Tn)` */
217247 type InverseMap [X <: Tuple , F [_]] <: Tuple = X match {
@@ -226,36 +256,15 @@ object Tuple {
226256 */
227257 type IsMappedBy [F [_]] = [X <: Tuple ] =>> X =:= Map [InverseMap [X , F ], F ]
228258
229- /** A tuple with the fields of tuple `X` in reversed order */
259+ /** A tuple with the elements of tuple `X` in reversed order */
230260 type Reverse [X <: Tuple ] = ReverseOnto [X , EmptyTuple ]
231261
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` */
233263 type ReverseOnto [X <: Tuple , Acc <: Tuple ] <: Tuple = X match
234264 case x *: xs => ReverseOnto [xs, x *: Acc ]
235265 case EmptyTuple => Acc
236266
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- }
254267
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 ])
259268
260269 /** Given a tuple `(T1, ..., Tn)`, returns a union of its
261270 * member types: `T1 | ... | Tn`. Returns `Nothing` if the tuple is empty.
@@ -377,7 +386,7 @@ object Tuple {
377386 case false => IndicesWhereHelper [t, P , S [N ]]
378387
379388 end helpers
380- }
389+ end Tuple
381390
382391/** A tuple of 0 elements */
383392type EmptyTuple = EmptyTuple .type
0 commit comments