@@ -101,75 +101,95 @@ sealed trait Tuple extends Product:
101
101
102
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 <: Tuple ] = X match {
116
+ /** The type of the first element of a tuple */
117
+ type Head [X <: Tuple ] = 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 <: Tuple ] <: 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 <: Tuple ] <: Tuple = X match {
124
- case _ *: xs => xs
125
- }
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]
126
143
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]
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
+ }
131
153
}
132
154
133
- /** Type of the concatenation of two tuples */
134
- type Concat [X <: Tuple , + Y <: Tuple ] <: Tuple = X match {
135
- case EmptyTuple => Y
136
- case x1 *: xs1 => x1 *: Concat [xs1, Y ]
137
- }
155
+ /** The pair type `(Take(X, N), Drop[X, N]). */
156
+ type Split [X <: Tuple , N <: Int ] = (Take [X , N ], Drop [X , N ])
138
157
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
- }
158
+ /** Type of a tuple with an element appended */
159
+ type Append [X <: Tuple , Y ] <: NonEmptyTuple = X match {
160
+ case EmptyTuple => Y *: EmptyTuple
161
+ case x *: xs => x *: Append [xs, Y ]
146
162
}
147
163
148
- /** Literal constant Int size of a tuple */
149
- type Size [X <: Tuple ] <: Int = X match {
150
- case EmptyTuple => 0
151
- case x *: xs => S [Size [xs]]
152
- }
164
+ /** Type of the concatenation of two tuples `X` and `Y` */
165
+ type Concat [X <: Tuple , + Y <: Tuple ] <: Tuple = X match
166
+ case EmptyTuple => Y
167
+ case x1 *: xs1 => x1 *: Concat [xs1, Y ]
153
168
154
169
/** Fold a tuple `(T1, ..., Tn)` into `F[T1, F[... F[Tn, Z]...]]]` */
155
170
type Fold [Tup <: Tuple , Z , F [_, _]] = Tup match
156
171
case EmptyTuple => Z
157
172
case h *: t => F [h, Fold [t, Z , F ]]
158
173
159
- /** Converts a tuple `(T1, ..., Tn)` to `(F[T1], ..., F[Tn])` */
160
- type Map [Tup <: Tuple , F [_ <: Union [Tup ]]] <: Tuple = Tup match {
174
+ /** The type of tuple `X` mapped with the type-level function `F`.
175
+ * If `X = (T1, ..., Ti)` then `Map[X, F] = `(F[T1], ..., F[Ti])`.
176
+ */
177
+ type Map [Tup <: Tuple , F [_ <: Union [Tup ]]] <: Tuple = Tup match
161
178
case EmptyTuple => EmptyTuple
162
179
case h *: t => F [h] *: Map [t, F ]
163
- }
164
180
165
- /** Converts a tuple `(T1, ..., Tn)` to a flattened `(..F[T1], ..., ..F[Tn])` */
166
- type FlatMap [Tup <: Tuple , F [_ <: Union [Tup ]] <: Tuple ] <: Tuple = Tup match {
181
+ /** The type of tuple `X` flat-mapped with the type-level function `F`.
182
+ * If `X = (T1, ..., Ti)` then `FlatMap[X, F] = `F[T1] ++ ... ++ F[Ti]`
183
+ */
184
+ type FlatMap [Tup <: Tuple , F [_ <: Union [Tup ]] <: Tuple ] <: Tuple = Tup match
167
185
case EmptyTuple => EmptyTuple
168
186
case h *: t => Concat [F [h], FlatMap [t, F ]]
169
- }
187
+ // TODO: implement term level analogue
170
188
171
- /** Filters out those members of the tuple for which the predicate `P` returns `false`.
172
- * A predicate `P[X]` is a type that can be either `true` or `false`. For example:
189
+ /** The type of the tuple consisting of all elements of tuple `X` that have types
190
+ * for which the given type level predicate `P` reduces to the literal
191
+ * constant `true`. A predicate `P[X]` is a type that can be either `true`
192
+ * or `false`. For example:
173
193
* ```scala
174
194
* type IsString[x] <: Boolean = x match {
175
195
* case String => true
@@ -233,29 +253,6 @@ object Tuple:
233
253
case x *: xs => ReverseOnto [xs, x *: Acc ]
234
254
case EmptyTuple => Acc
235
255
236
- /** Transforms a tuple `(T1, ..., Tn)` into `(T1, ..., Ti)`. */
237
- type Take [T <: Tuple , N <: Int ] <: Tuple = N match {
238
- case 0 => EmptyTuple
239
- case S [n1] => T match {
240
- case EmptyTuple => EmptyTuple
241
- case x *: xs => x *: Take [xs, n1]
242
- }
243
- }
244
-
245
- /** Transforms a tuple `(T1, ..., Tn)` into `(Ti+1, ..., Tn)`. */
246
- type Drop [T <: Tuple , N <: Int ] <: Tuple = N match {
247
- case 0 => T
248
- case S [n1] => T match {
249
- case EmptyTuple => EmptyTuple
250
- case x *: xs => Drop [xs, n1]
251
- }
252
- }
253
-
254
- /** Splits a tuple (T1, ..., Tn) into a pair of two tuples `(T1, ..., Ti)` and
255
- * `(Ti+1, ..., Tn)`.
256
- */
257
- type Split [T <: Tuple , N <: Int ] = (Take [T , N ], Drop [T , N ])
258
-
259
256
/** Given a tuple `(T1, ..., Tn)`, returns a union of its
260
257
* member types: `T1 | ... | Tn`. Returns `Nothing` if the tuple is empty.
261
258
*/
0 commit comments