From 381589c270fbfb3e9b8756bfedf68e9e760d7e23 Mon Sep 17 00:00:00 2001 From: Anatolii Date: Fri, 16 Aug 2019 17:09:07 +0200 Subject: [PATCH 1/2] Zip tuple operation implemented --- library/src-bootstrapped/scala/TupleOps.scala | 34 +++++++++++++++++++ tests/neg/tuple-zip.scala | 6 ++++ tests/pos/tuple-zip.scala | 6 ++++ 3 files changed, 46 insertions(+) create mode 100644 library/src-bootstrapped/scala/TupleOps.scala create mode 100644 tests/neg/tuple-zip.scala create mode 100644 tests/pos/tuple-zip.scala diff --git a/library/src-bootstrapped/scala/TupleOps.scala b/library/src-bootstrapped/scala/TupleOps.scala new file mode 100644 index 000000000000..2022f4721052 --- /dev/null +++ b/library/src-bootstrapped/scala/TupleOps.scala @@ -0,0 +1,34 @@ +package scala +import annotation.showAsInfix +import compiletime._ +import internal._ + +given TupleOps[T1 <: Tuple](t1: T1) { + import tupleops._ + + def zip[T2 <: Tuple, U <: Tuple](t2: T2) given (z: Zip.Aux[T1, T2, U]): U = z(t1, t2) +} + +object tupleops { + trait Zip[T1 <: Tuple, T2 <: Tuple] { + type Res <: Tuple + def apply(t1: T1, t2: T2): Res + } + + object Zip { + import Tuple.{ Head, Tail } + + type Aux[T1 <: Tuple, T2 <: Tuple, Res0] = Zip[T1, T2] { type Res = Res0 } + + given [T1 <: NonEmptyTuple, T2 <: NonEmptyTuple, TZ <: Tuple] as Aux[T1, T2, (Head[T1], Head[T2]) *: TZ] + given (tz: Aux[Tail[T1], Tail[T2], TZ]) = new Zip[T1, T2] { + type Res = (Head[T1], Head[T2]) *: TZ + def apply(t1: T1, t2: T2): Res = (t1.head, t2.head) *: tz(t1.tail, t2.tail) + } + + given as Aux[Unit, Unit, Unit] = new Zip[Unit, Unit] { + type Res = Unit + def apply(t1: Unit, t2: Unit): Unit = () + } + } +} \ No newline at end of file diff --git a/tests/neg/tuple-zip.scala b/tests/neg/tuple-zip.scala new file mode 100644 index 000000000000..b079a90119b6 --- /dev/null +++ b/tests/neg/tuple-zip.scala @@ -0,0 +1,6 @@ +import given scala.TupleOps + +val x: (1, 2, 3) = (1, 2, 3) +val y: (4, 5, 6) = (4, 5, 6) + +val z: ((1, 4), (2, 5), (3, 3)) = x.zip(y) // error diff --git a/tests/pos/tuple-zip.scala b/tests/pos/tuple-zip.scala new file mode 100644 index 000000000000..9826c7289ecf --- /dev/null +++ b/tests/pos/tuple-zip.scala @@ -0,0 +1,6 @@ +import given scala.TupleOps + +val x: (1, 2, 3) = (1, 2, 3) +val y: (4, 5, 6) = (4, 5, 6) + +val z: ((1, 4), (2, 5), (3, 6)) = x.zip(y) From 25e9aac752c954e3e05b11f5a52c760261ee70f5 Mon Sep 17 00:00:00 2001 From: Anatolii Date: Mon, 19 Aug 2019 14:06:25 +0200 Subject: [PATCH 2/2] WIP tuple map --- library/src-bootstrapped/scala/TupleOps.scala | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/library/src-bootstrapped/scala/TupleOps.scala b/library/src-bootstrapped/scala/TupleOps.scala index 2022f4721052..bf3694fcc588 100644 --- a/library/src-bootstrapped/scala/TupleOps.scala +++ b/library/src-bootstrapped/scala/TupleOps.scala @@ -7,18 +7,19 @@ given TupleOps[T1 <: Tuple](t1: T1) { import tupleops._ def zip[T2 <: Tuple, U <: Tuple](t2: T2) given (z: Zip.Aux[T1, T2, U]): U = z(t1, t2) + def map[F[_], R <: Tuple](f: [t] => t => F[t]) given (m: Map.Aux[T1, F, R]): R = m(t1, f) } object tupleops { + import Tuple.{ Head, Tail } + trait Zip[T1 <: Tuple, T2 <: Tuple] { type Res <: Tuple def apply(t1: T1, t2: T2): Res } object Zip { - import Tuple.{ Head, Tail } - - type Aux[T1 <: Tuple, T2 <: Tuple, Res0] = Zip[T1, T2] { type Res = Res0 } + type Aux[T1 <: Tuple, T2 <: Tuple, Res0 <: Tuple] = Zip[T1, T2] { type Res = Res0 } given [T1 <: NonEmptyTuple, T2 <: NonEmptyTuple, TZ <: Tuple] as Aux[T1, T2, (Head[T1], Head[T2]) *: TZ] given (tz: Aux[Tail[T1], Tail[T2], TZ]) = new Zip[T1, T2] { @@ -31,4 +32,24 @@ object tupleops { def apply(t1: Unit, t2: Unit): Unit = () } } -} \ No newline at end of file + + trait Map[T <: Tuple, F[_]] { + type Res <: Tuple + def apply(t: T, f: [t] => t => F[t]): Res + } + + object Map { + type Aux[T <: Tuple, F[_], Res0 <: Tuple] = Map[T, F] { type Res = Res0 } + + given [T <: NonEmptyTuple, F[_], MT <: Tuple] as Aux[T, F, F[Head[T]] *: MT] + given (mt: Aux[Tail[T], F, MT]) = new Map[T, F] { + type Res = F[Head[T]] *: MT + def apply(t: T, f: [t] => t => F[t]): Res = f(t.head) *: mt(t.tail, f) + } + + given [F[_]] as Aux[Unit, F, Unit] = new Map[Unit, F] { + type Res = Unit + def apply(t: Unit, f: [t] => t => F[t]): Unit = t + } + } +}