diff --git a/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala b/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala index 67259e8d7..41fb9cc5e 100644 --- a/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala +++ b/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala @@ -308,10 +308,11 @@ trait Cont: tupleMapRepr.asType match case '[tupleMap] => '{ - given Applicative[F] = $applicativeExpr - import TupleMapExtension.* - ${ br.tupleExpr.asInstanceOf[Expr[Tuple.Map[inputTypeTpe & Tuple, F]]] } - .mapN(${ lambda.asExprOf[inputTypeTpe & Tuple => A1] }) + $applicativeExpr.mapN( + ${ br.tupleExpr.asInstanceOf[Expr[Tuple.Map[inputTypeTpe & Tuple, F]]] } + )( + ${ lambda.asExprOf[inputTypeTpe & Tuple => A1] } + ) } eitherTree match case Left(_) => diff --git a/main-settings/src/main/scala/sbt/Structure.scala b/main-settings/src/main/scala/sbt/Structure.scala index ff361d604..3d52545db 100644 --- a/main-settings/src/main/scala/sbt/Structure.scala +++ b/main-settings/src/main/scala/sbt/Structure.scala @@ -347,14 +347,10 @@ object Scoped: protected def onTask[A2](f: Task[A1] => Task[A2]): Initialize[Task[A2]] = init.apply(f) - def flatMapTaskValue[T](f: A1 => Task[T]): Initialize[Task[T]] = - onTask(_.result flatMap (f compose successM)) - def map[A2](f: A1 => A2): Initialize[Task[A2]] = - onTask(_.result map (f compose successM)) - def andFinally(fin: => Unit): Initialize[Task[A1]] = - onTask(_ andFinally fin) - def doFinally(t: Task[Unit]): Initialize[Task[A1]] = - onTask(_ doFinally t) + def flatMapTaskValue[T](f: A1 => Task[T]): Initialize[Task[T]] = onTask(_.flatMap(f)) + def map[A2](f: A1 => A2): Initialize[Task[A2]] = onTask(_.map(f)) + def andFinally(fin: => Unit): Initialize[Task[A1]] = onTask(_.andFinally(fin)) + def doFinally(t: Task[Unit]): Initialize[Task[A1]] = onTask(_.doFinally(t)) def ||[T >: A1](alt: Task[T]): Initialize[Task[T]] = onTask(_ || alt) def &&[T](alt: Task[T]): Initialize[Task[T]] = onTask(_ && alt) def tag(tags: Tag*): Initialize[Task[A1]] = onTask(_.tag(tags: _*)) @@ -842,4 +838,4 @@ class TupleWrap[Tup <: Tuple](value: Tuple.Map[Tup, Taskable]): type InitTask[A2] = Initialize[Task[A2]] lazy val initTasks = value.transform[InitTask]([a] => (t: Taskable[a]) => t.toTask) def mapN[A1](f: Tup => A1): Def.Initialize[Task[A1]] = - initTasks.mapN[A1](f)(using std.FullInstance.initializeTaskMonad) + std.FullInstance.initializeTaskMonad.mapN(initTasks)(f) diff --git a/main-settings/src/main/scala/sbt/std/Instances.scala b/main-settings/src/main/scala/sbt/std/Instances.scala index 1bf8c4888..e9f5cae3e 100644 --- a/main-settings/src/main/scala/sbt/std/Instances.scala +++ b/main-settings/src/main/scala/sbt/std/Instances.scala @@ -19,6 +19,8 @@ object InitializeInstance: override def pure[A1](a: () => A1): Initialize[A1] = Def.pure(a) override def map[A1, A2](in: Initialize[A1])(f: A1 => A2): Initialize[A2] = in(f) + override def mapN[A1 <: Tuple, A2](t: Tuple.Map[A1, Initialize])(f: A1 => A2): Initialize[A2] = + Def.app(t)(f) override def ap[A1, A2](ff: Initialize[A1 => A2])(fa: Initialize[A1]): Initialize[A2] = Def.ap[A1, A2](ff)(fa) override def flatMap[A1, A2](fa: Initialize[A1])(f: A1 => Initialize[A2]) = @@ -63,6 +65,10 @@ object FullInstance: override def map[A1, A2](fa: Initialize[Task[A1]])(f: A1 => A2): Initialize[Task[A2]] = F1F2.map(fa)(f) + override def mapN[A1 <: Tuple, A2](t: Tuple.Map[A1, [a] =>> Initialize[Task[a]]])( + f: A1 => A2 + ): Initialize[Task[A2]] = F1F2.mapN(t)(f) + override def ap[A1, A2](ff: Initialize[Task[A1 => A2]])( fa: Initialize[Task[A1]] ): Initialize[Task[A2]] = diff --git a/tasks-standard/src/main/scala/sbt/Task.scala b/tasks-standard/src/main/scala/sbt/Task.scala index 0e0833db8..5995ce01a 100644 --- a/tasks-standard/src/main/scala/sbt/Task.scala +++ b/tasks-standard/src/main/scala/sbt/Task.scala @@ -50,6 +50,7 @@ object Task: } override def map[A1, A2](in: Task[A1])(f: A1 => A2): Task[A2] = in.map(f) + override def mapN[A1 <: Tuple, A2](t: Tuple.Map[A1, Task])(f: A1 => A2): Task[A2] = t.mapN(f) override def flatMap[A1, A2](in: F[A1])(f: A1 => F[A2]): F[A2] = in.flatMap(f) override def flatten[A1](in: Task[Task[A1]]): Task[A1] = in.flatMap(identity) end Task diff --git a/util-collection/src/main/scala/sbt/internal/util/TupleMapExtension.scala b/util-collection/src/main/scala/sbt/internal/util/TupleMapExtension.scala index ca0ceb71d..9c84e02cc 100644 --- a/util-collection/src/main/scala/sbt/internal/util/TupleMapExtension.scala +++ b/util-collection/src/main/scala/sbt/internal/util/TupleMapExtension.scala @@ -5,10 +5,7 @@ * Licensed under Apache License 2.0 (see LICENSE) */ -package sbt.internal -package util - -import sbt.util.Applicative +package sbt.internal.util object TupleMapExtension: extension [Tup <: Tuple, F1[_]](tuple: Tuple.Map[Tup, F1]) @@ -54,14 +51,4 @@ object TupleMapExtension: case _ => scala.runtime.TupleXXL.fromIterator(tuple.iterator.map(f(_))) // format: on res.asInstanceOf[Tuple.Map[Tup, F2]] - - def traverse[F2[_]](f: [a] => F1[a] => F2[a])(using app: Applicative[F2]): F2[Tup] = - val fxs: F2[List[Any]] = tuple.iterator - .foldRight[F2[List[Any]]](app.pure(() => Nil))((x, xs) => - app.map(app.product(f(x), xs))((h, t) => h :: t) - ) - app.map(fxs)(xs => Tuple.fromArray(xs.toArray).asInstanceOf[Tup]) - - def mapN[A1](f: Tup => A1)(using app: Applicative[F1]): F1[A1] = - app.map(tuple.traverse[F1]([a] => (f: F1[a]) => f))(f) end TupleMapExtension diff --git a/util-collection/src/main/scala/sbt/util/Applicative.scala b/util-collection/src/main/scala/sbt/util/Applicative.scala index 16d558d46..99e23db67 100644 --- a/util-collection/src/main/scala/sbt/util/Applicative.scala +++ b/util-collection/src/main/scala/sbt/util/Applicative.scala @@ -10,6 +10,18 @@ package sbt.util trait Applicative[F[_]] extends Apply[F]: def pure[A1](x: () => A1): F[A1] + def mapN[A1 <: Tuple, A2](t: Tuple.Map[A1, F])(f: A1 => A2): F[A2] = + import sbt.internal.util.TupleMapExtension.* + val g = (l: List[Any]) => f(Tuple.fromArray(l.toArray).asInstanceOf[A1]) + map( + t.iterator.foldLeft(pure(() => g))((g, head) => + ap(map(head)(h => (f: List[Any] => A2) => (tail: List[Any]) => f(h :: tail)))(g) + ) + )(_.apply(Nil)) + + def map2(t: (F[Int], F[String]))(f: (Int, String) => Boolean): F[Boolean] = + ap(ap(pure(() => f.curried))(t._1))(t._2) + override def map[A1, A2](fa: F[A1])(f: A1 => A2): F[A2] = ap(pure(() => f))(fa) end Applicative @@ -25,6 +37,8 @@ object Applicative: override def pure[A1](x: () => A1): F1[F2[A1]] = F1.pure(() => F2.pure(x)) override def map[A1, A2](fa: F1[F2[A1]])(f: A1 => A2): F1[F2[A2]] = F1.map(fa)(f2 => F2.map(f2)(f)) + override def mapN[A1 <: Tuple, A2](t1: Tuple.Map[A1, F])(f: A1 => A2): F1[F2[A2]] = + F1.mapN(t1.asInstanceOf[Tuple.Map[Tuple.Map[A1, F2], F1]])(t2 => F2.mapN(t2)(f)) override def ap[A1, A2](f1f2f: F1[F2[A1 => A2]])(f1f2a: F1[F2[A1]]): F1[F2[A2]] = F1.ap(F1.map(f1f2f) { (f2f: F2[A1 => A2]) => (f2a: F2[A1]) => F2.ap(f2f)(f2a) })(f1f2a) diff --git a/util-collection/src/main/scala/sbt/util/Apply.scala b/util-collection/src/main/scala/sbt/util/Apply.scala index 8d20bdd0b..18ee6e1be 100644 --- a/util-collection/src/main/scala/sbt/util/Apply.scala +++ b/util-collection/src/main/scala/sbt/util/Apply.scala @@ -9,9 +9,6 @@ package sbt.util trait Apply[F[_]] extends Functor[F]: def ap[A1, A2](ff: F[A1 => A2])(fa: F[A1]): F[A2] - - def product[A1, A2](fa: F[A1], fb: F[A2]): F[(A1, A2)] = - ap(map(fa)(a => (b: A2) => (a, b)))(fb) end Apply object Apply: diff --git a/util-collection/src/test/scala/TupleMapExtensionTest.scala b/util-collection/src/test/scala/TupleMapExtensionTest.scala deleted file mode 100644 index f0849277f..000000000 --- a/util-collection/src/test/scala/TupleMapExtensionTest.scala +++ /dev/null @@ -1,12 +0,0 @@ -package sbt.internal.util - -import verify.BasicTestSuite - -object TupleMapExtensionTest extends BasicTestSuite: - val tuple: Tuple.Map[(Int, String), Option] = ((Option(1), Option("foo"))) - - test("tuple.mapN") { - val f = (arg: (Int, String)) => arg._1.toString + "|" + arg._2 - val actual = TupleMapExtension.mapN[(Int, String), Option](tuple)(f) - assert(actual == Option("1|foo")) - }