Skip to content

Commit 40c6138

Browse files
EugeneFlesselleodersky
authored andcommitted
Reorder operations to be same between term and type level
1 parent 5df2120 commit 40c6138

File tree

1 file changed

+101
-101
lines changed

1 file changed

+101
-101
lines changed

library/src/scala/Tuple.scala

Lines changed: 101 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,22 @@ sealed trait Tuple extends Product:
2121
inline def toIArray: IArray[Object] =
2222
runtime.Tuples.toIArray(this)
2323

24-
/** Return a copy of `this` tuple with an element appended */
25-
inline def :* [This >: this.type <: Tuple, L](x: L): This :* L =
26-
runtime.Tuples.append(x, this).asInstanceOf[Append[This, L]]
27-
2824
/** Return a new tuple by prepending the element to `this` tuple.
2925
* This operation is O(this.size)
3026
*/
3127
inline def *: [H, This >: this.type <: Tuple](x: H): H *: This =
3228
runtime.Tuples.cons(x, this).asInstanceOf[H *: This]
3329

30+
/** Return a copy of `this` tuple with an element appended */
31+
inline def :* [This >: this.type <: Tuple, L](x: L): This :* L =
32+
runtime.Tuples.append(x, this).asInstanceOf[Append[This, L]]
33+
34+
/** Return the size (or arity) of the tuple */
35+
inline def size[This >: this.type <: Tuple]: Size[This] =
36+
runtime.Tuples.size(this).asInstanceOf[Size[This]]
37+
3438
/** Get the i-th element of this tuple.
35-
* Equivalent to productElement but with a precise return type.
39+
* Equivalent to productElement but with a precise return type.
3640
*/
3741
inline def apply[This >: this.type <: Tuple](n: Int): Elem[This, n.type] =
3842
runtime.Tuples.apply(this, n).asInstanceOf[Elem[This, n.type]]
@@ -41,19 +45,38 @@ sealed trait Tuple extends Product:
4145
inline def head[This >: this.type <: Tuple]: Head[This] =
4246
runtime.Tuples.apply(this, 0).asInstanceOf[Head[This]]
4347

44-
/** Get the initial part of the tuple without its last element */
45-
inline def init[This >: this.type <: Tuple]: Init[This] =
46-
runtime.Tuples.init(this).asInstanceOf[Init[This]]
48+
/** Get the tail of this tuple.
49+
* This operation is O(this.size)
50+
*/
51+
inline def tail[This >: this.type <: Tuple]: Tail[This] =
52+
runtime.Tuples.tail(this).asInstanceOf[Tail[This]]
4753

4854
/** Get the last of this tuple */
4955
inline def last[This >: this.type <: Tuple]: Last[This] =
5056
runtime.Tuples.last(this).asInstanceOf[Last[This]]
5157

52-
/** Get the tail of this tuple.
53-
* This operation is O(this.size)
58+
/** Get the initial part of the tuple without its last element */
59+
inline def init[This >: this.type <: Tuple]: Init[This] =
60+
runtime.Tuples.init(this).asInstanceOf[Init[This]]
61+
62+
/** Given a tuple `(a1, ..., am)`, returns the tuple `(a1, ..., an)` consisting
63+
* of its first n elements.
5464
*/
55-
inline def tail[This >: this.type <: Tuple]: Tail[This] =
56-
runtime.Tuples.tail(this).asInstanceOf[Tail[This]]
65+
inline def take[This >: this.type <: Tuple](n: Int): Take[This, n.type] =
66+
runtime.Tuples.take(this, n).asInstanceOf[Take[This, n.type]]
67+
68+
/** Given a tuple `(a1, ..., am)`, returns the tuple `(an+1, ..., am)` consisting
69+
* all its elements except the first n ones.
70+
*/
71+
inline def drop[This >: this.type <: Tuple](n: Int): Drop[This, n.type] =
72+
runtime.Tuples.drop(this, n).asInstanceOf[Drop[This, n.type]]
73+
74+
/** Given a tuple `(a1, ..., am)`, returns a pair of the tuple `(a1, ..., an)`
75+
* consisting of the first n elements, and the tuple `(an+1, ..., am)` consisting
76+
* of the remaining elements.
77+
*/
78+
inline def splitAt[This >: this.type <: Tuple](n: Int): Split[This, n.type] =
79+
runtime.Tuples.splitAt(this, n).asInstanceOf[Split[This, n.type]]
5780

5881
/** Return a new tuple by concatenating `this` tuple with `that` tuple.
5982
* This operation is O(this.size + that.size)
@@ -63,10 +86,6 @@ sealed trait Tuple extends Product:
6386
inline def ++ [This >: this.type <: Tuple](that: Tuple): This ++ that.type =
6487
runtime.Tuples.concat(this, that).asInstanceOf[Concat[This, that.type]]
6588

66-
/** Return the size (or arity) of the tuple */
67-
inline def size[This >: this.type <: Tuple]: Size[This] =
68-
runtime.Tuples.size(this).asInstanceOf[Size[This]]
69-
7089
/** Given two tuples, `(a1, ..., an)` and `(a1, ..., an)`, returns a tuple
7190
* `((a1, b1), ..., (an, bn))`. If the two tuples have different sizes,
7291
* the extra elements of the larger tuple will be disregarded.
@@ -85,24 +104,11 @@ sealed trait Tuple extends Product:
85104
inline def map[F[_]](f: [t] => t => F[t]): Map[this.type, F] =
86105
runtime.Tuples.map(this, f).asInstanceOf[Map[this.type, F]]
87106

88-
/** Given a tuple `(a1, ..., am)`, returns the tuple `(a1, ..., an)` consisting
89-
* of its first n elements.
90-
*/
91-
inline def take[This >: this.type <: Tuple](n: Int): Take[This, n.type] =
92-
runtime.Tuples.take(this, n).asInstanceOf[Take[This, n.type]]
93-
94-
/** Given a tuple `(a1, ..., am)`, returns the tuple `(an+1, ..., am)` consisting
95-
* all its elements except the first n ones.
96-
*/
97-
inline def drop[This >: this.type <: Tuple](n: Int): Drop[This, n.type] =
98-
runtime.Tuples.drop(this, n).asInstanceOf[Drop[This, n.type]]
99-
100-
/** Given a tuple `(a1, ..., am)`, returns a pair of the tuple `(a1, ..., an)`
101-
* consisting of the first n elements, and the tuple `(an+1, ..., am)` consisting
102-
* of the remaining elements.
103-
*/
104-
inline def splitAt[This >: this.type <: Tuple](n: Int): Split[This, n.type] =
105-
runtime.Tuples.splitAt(this, n).asInstanceOf[Split[This, n.type]]
107+
/** A tuple consisting of all elements of this tuple that satisfy the predicate `p`. */
108+
inline def filter[This >: this.type <: Tuple, P[_ <: Union[This]] <: Boolean]
109+
(p: (x: Union[This]) => P[x.type]): Filter[This, P] =
110+
val arr = this.toArray.filter(x => p(x.asInstanceOf[Union[This]]))
111+
Tuple.fromArray(arr).asInstanceOf[Filter[This, P]]
106112

107113
/** Given a tuple `(a1, ..., am)`, returns the reversed tuple `(am, ..., a1)`
108114
* consisting all its elements.
@@ -114,14 +120,16 @@ sealed trait Tuple extends Product:
114120
inline def reverseOnto[This >: this.type <: Tuple, Acc <: Tuple](acc: Acc): ReverseOnto[This, Acc] =
115121
(this.reverse ++ acc).asInstanceOf[ReverseOnto[This, Acc]]
116122

117-
/** A tuple consisting of all elements of this tuple that satisfy the predicate `p`. */
118-
inline def filter[This >: this.type <: Tuple, P[_ <: Union[This]] <: Boolean]
119-
(p: (x: Union[This]) => P[x.type]): Filter[This, P] =
120-
val arr = this.toArray.filter(x => p(x.asInstanceOf[Union[This]]))
121-
Tuple.fromArray(arr).asInstanceOf[Filter[This, P]]
122-
123123
object Tuple:
124124

125+
/** Type of a tuple with an element appended */
126+
type Append[X <: Tuple, +Y] <: NonEmptyTuple = X match
127+
case EmptyTuple => Y *: EmptyTuple
128+
case x *: xs => x *: Append[xs, Y]
129+
130+
/** An infix shorthand for `Append[X, Y]` */
131+
infix type :*[X <: Tuple, +Y] = Append[X, Y]
132+
125133
/** The size of a tuple, represented as a literal constant subtype of Int */
126134
type Size[X <: Tuple] <: Int = X match
127135
case EmptyTuple => 0
@@ -142,15 +150,15 @@ object Tuple:
142150
type Head[X <: Tuple] = X match
143151
case x *: _ => x
144152

153+
/** The type of a tuple consisting of all elements of tuple X except the first one */
154+
type Tail[X <: Tuple] <: Tuple = X match
155+
case _ *: xs => xs
156+
145157
/** The type of the last element of a tuple */
146158
type Last[X <: Tuple] = X match
147159
case x *: EmptyTuple => x
148160
case _ *: xs => Last[xs]
149161

150-
/** The type of a tuple consisting of all elements of tuple X except the first one */
151-
type Tail[X <: Tuple] <: Tuple = X match
152-
case _ *: xs => xs
153-
154162
/** The type of the initial part of a tuple without its last element */
155163
type Init[X <: Tuple] <: Tuple = X match
156164
case _ *: EmptyTuple => EmptyTuple
@@ -177,14 +185,6 @@ object Tuple:
177185
/** The pair type `(Take(X, N), Drop[X, N]). */
178186
type Split[X <: Tuple, N <: Int] = (Take[X, N], Drop[X, N])
179187

180-
/** Type of a tuple with an element appended */
181-
type Append[X <: Tuple, +Y] <: NonEmptyTuple = X match
182-
case EmptyTuple => Y *: EmptyTuple
183-
case x *: xs => x *: Append[xs, Y]
184-
185-
/** An infix shorthand for `Append[X, Y]` */
186-
infix type :*[X <: Tuple, +Y] = Append[X, Y]
187-
188188
/** Type of the concatenation of two tuples `X` and `Y` */
189189
// Can be covariant in `Y` since it never appears as a match type scrutinee.
190190
type Concat[X <: Tuple, +Y <: Tuple] <: Tuple = X match
@@ -194,18 +194,25 @@ object Tuple:
194194
/** An infix shorthand for `Concat[X, Y]` */
195195
infix type ++[X <: Tuple, +Y <: Tuple] = Concat[X, Y]
196196

197-
/** The index of `Y` in tuple `X` as a literal constant Int,
198-
* or `Size[X]` if `Y` is disjoint from all element types in `X`.
197+
/** The type of the tuple consisting of all element values of
198+
* tuple `X` zipped with corresponding elements of tuple `Y`.
199+
* If the two tuples have different sizes,
200+
* the extra elements of the larger tuple will be disregarded.
201+
* For example, if
202+
* ```
203+
* X = (S1, ..., Si)
204+
* Y = (T1, ..., Tj) where j >= i
205+
* ```
206+
* then
207+
* ```
208+
* Zip[X, Y] = ((S1, T1), ..., (Si, Ti))
209+
* ```
210+
* @syntax markdown
199211
*/
200-
type IndexOf[X <: Tuple, Y] <: Int = X match
201-
case Y *: _ => 0
202-
case _ *: xs => S[IndexOf[xs, Y]]
203-
case EmptyTuple => 0
204-
205-
/** Fold a tuple `(T1, ..., Tn)` into `F[T1, F[... F[Tn, Z]...]]]` */
206-
type Fold[X <: Tuple, Z, F[_, _]] = X match
207-
case EmptyTuple => Z
208-
case x *: xs => F[x, Fold[xs, Z, F]]
212+
type Zip[X <: Tuple, Y <: Tuple] <: Tuple = (X, Y) match
213+
case (x *: xs, y *: ys) => (x, y) *: Zip[xs, ys]
214+
case (EmptyTuple, _) => EmptyTuple
215+
case (_, EmptyTuple) => EmptyTuple
209216

210217
/** The type of tuple `X` mapped with the type-level function `F`.
211218
* If `X = (T1, ..., Ti)` then `Map[X, F] = `(F[T1], ..., F[Ti])`.
@@ -214,6 +221,18 @@ object Tuple:
214221
case EmptyTuple => EmptyTuple
215222
case x *: xs => F[x] *: Map[xs, F]
216223

224+
/** Converts a tuple `(F[T1], ..., F[Tn])` to `(T1, ... Tn)` */
225+
type InverseMap[X <: Tuple, F[_]] <: Tuple = X match
226+
case F[x] *: xs => x *: InverseMap[xs, F]
227+
case EmptyTuple => EmptyTuple
228+
229+
/** Implicit evidence. IsMappedBy[F][X] is present in the implicit scope iff
230+
* X is a tuple for which each element's type is constructed via `F`. E.g.
231+
* (F[A1], ..., F[An]), but not `(F[A1], B2, ..., F[An])` where B2 does not
232+
* have the shape of `F[A]`.
233+
*/
234+
type IsMappedBy[F[_]] = [X <: Tuple] =>> X =:= Map[InverseMap[X, F], F]
235+
217236
/** The type of tuple `X` flat-mapped with the type-level function `F`.
218237
* If `X = (T1, ..., Ti)` then `FlatMap[X, F] = `F[T1] ++ ... ++ F[Ti]`
219238
*/
@@ -241,44 +260,6 @@ object Tuple:
241260
case true => x *: Filter[xs, P]
242261
case false => Filter[xs, P]
243262

244-
/** A tuple consisting of those indices `N` of tuple `X` where the predicate `P`
245-
* is true for `Elem[X, N]`. Indices are type level values <: Int.
246-
*/
247-
type IndicesWhere[X <: Tuple, P[_ <: Union[X]] <: Boolean] =
248-
helpers.IndicesWhereHelper[X, P, 0]
249-
250-
/** The type of the tuple consisting of all element values of
251-
* tuple `X` zipped with corresponding elements of tuple `Y`.
252-
* If the two tuples have different sizes,
253-
* the extra elements of the larger tuple will be disregarded.
254-
* For example, if
255-
* ```
256-
* X = (S1, ..., Si)
257-
* Y = (T1, ..., Tj) where j >= i
258-
* ```
259-
* then
260-
* ```
261-
* Zip[X, Y] = ((S1, T1), ..., (Si, Ti))
262-
* ```
263-
* @syntax markdown
264-
*/
265-
type Zip[X <: Tuple, Y <: Tuple] <: Tuple = (X, Y) match
266-
case (x *: xs, y *: ys) => (x, y) *: Zip[xs, ys]
267-
case (EmptyTuple, _) => EmptyTuple
268-
case (_, EmptyTuple) => EmptyTuple
269-
270-
/** Converts a tuple `(F[T1], ..., F[Tn])` to `(T1, ... Tn)` */
271-
type InverseMap[X <: Tuple, F[_]] <: Tuple = X match
272-
case F[x] *: xs => x *: InverseMap[xs, F]
273-
case EmptyTuple => EmptyTuple
274-
275-
/** Implicit evidence. IsMappedBy[F][X] is present in the implicit scope iff
276-
* X is a tuple for which each element's type is constructed via `F`. E.g.
277-
* (F[A1], ..., F[An]), but not `(F[A1], B2, ..., F[An])` where B2 does not
278-
* have the shape of `F[A]`.
279-
*/
280-
type IsMappedBy[F[_]] = [X <: Tuple] =>> X =:= Map[InverseMap[X, F], F]
281-
282263
/** A tuple with the elements of tuple `X` in reversed order */
283264
type Reverse[X <: Tuple] = ReverseOnto[X, EmptyTuple]
284265

@@ -287,11 +268,30 @@ object Tuple:
287268
case x *: xs => ReverseOnto[xs, x *: Acc]
288269
case EmptyTuple => Acc
289270

271+
/** Fold a tuple `(T1, ..., Tn)` into `F[T1, F[... F[Tn, Z]...]]]` */
272+
type Fold[X <: Tuple, Z, F[_, _]] = X match
273+
case EmptyTuple => Z
274+
case x *: xs => F[x, Fold[xs, Z, F]]
275+
290276
/** Given a tuple `(T1, ..., Tn)`, returns a union of its
291277
* member types: `T1 | ... | Tn`. Returns `Nothing` if the tuple is empty.
292278
*/
293279
type Union[T <: Tuple] = Fold[T, Nothing, [x, y] =>> x | y]
294280

281+
/** The index of `Y` in tuple `X` as a literal constant Int,
282+
* or `Size[X]` if `Y` is disjoint from all element types in `X`.
283+
*/
284+
type IndexOf[X <: Tuple, Y] <: Int = X match
285+
case Y *: _ => 0
286+
case _ *: xs => S[IndexOf[xs, Y]]
287+
case EmptyTuple => 0
288+
289+
/** A tuple consisting of those indices `N` of tuple `X` where the predicate `P`
290+
* is true for `Elem[X, N]`. Indices are type level values <: Int.
291+
*/
292+
type IndicesWhere[X <: Tuple, P[_ <: Union[X]] <: Boolean] =
293+
helpers.IndicesWhereHelper[X, P, 0]
294+
295295
/** A type level Boolean indicating whether the tuple `X` has an element
296296
* that matches `Y`.
297297
* @pre The elements of `X` are assumed to be singleton types

0 commit comments

Comments
 (0)