Skip to content

Commit 5157438

Browse files
committed
Improvements to tuples: Rearrange types into a more logical order
1 parent 216fc92 commit 5157438

File tree

1 file changed

+64
-67
lines changed

1 file changed

+64
-67
lines changed

library/src/scala/Tuple.scala

+64-67
Original file line numberDiff line numberDiff line change
@@ -101,75 +101,95 @@ sealed trait Tuple extends Product:
101101

102102
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 <: Tuple] = X match {
116+
/** The type of the first element of a tuple */
117+
type Head[X <: Tuple] = 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 <: 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
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 <: 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]
126143

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+
}
131153
}
132154

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])
138157

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]
146162
}
147163

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]
153168

154169
/** Fold a tuple `(T1, ..., Tn)` into `F[T1, F[... F[Tn, Z]...]]]` */
155170
type Fold[Tup <: Tuple, Z, F[_, _]] = Tup match
156171
case EmptyTuple => Z
157172
case h *: t => F[h, Fold[t, Z, F]]
158173

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
161178
case EmptyTuple => EmptyTuple
162179
case h *: t => F[h] *: Map[t, F]
163-
}
164180

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
167185
case EmptyTuple => EmptyTuple
168186
case h *: t => Concat[F[h], FlatMap[t, F]]
169-
}
187+
// TODO: implement term level analogue
170188

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:
173193
* ```scala
174194
* type IsString[x] <: Boolean = x match {
175195
* case String => true
@@ -233,29 +253,6 @@ object Tuple:
233253
case x *: xs => ReverseOnto[xs, x *: Acc]
234254
case EmptyTuple => Acc
235255

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-
259256
/** Given a tuple `(T1, ..., Tn)`, returns a union of its
260257
* member types: `T1 | ... | Tn`. Returns `Nothing` if the tuple is empty.
261258
*/

0 commit comments

Comments
 (0)