diff --git a/build.sbt b/build.sbt index 3d7293d477..3703da6f74 100644 --- a/build.sbt +++ b/build.sbt @@ -1,4 +1,4 @@ -ThisBuild / tlBaseVersion := "2.12" +ThisBuild / tlBaseVersion := "2.13" val scalaCheckVersion = "1.18.1" diff --git a/core/src/main/scala/cats/syntax/apply.scala b/core/src/main/scala/cats/syntax/apply.scala index dcb0d95a67..55fd2fd87e 100644 --- a/core/src/main/scala/cats/syntax/apply.scala +++ b/core/src/main/scala/cats/syntax/apply.scala @@ -22,7 +22,7 @@ package cats package syntax -trait ApplySyntax extends TupleSemigroupalSyntax with FunctionApplySyntax { +trait ApplySyntax extends TupleSemigroupalSyntax with FunctionApplySyntax with FunctionApplySyntax2 { @deprecated("Kept for binary compatibility", "2.10.0") final def catsSyntaxApply[F[_], A](fa: F[A], F: Apply[F]): Apply.Ops[F, A] = new Apply.Ops[F, A] { diff --git a/project/Boilerplate.scala b/project/Boilerplate.scala index 58955aa3c4..b773de55e8 100644 --- a/project/Boilerplate.scala +++ b/project/Boilerplate.scala @@ -33,6 +33,7 @@ object Boilerplate { GenParallelArityFunctions2, GenFoldableArityFunctions, GenFunctionSyntax, + GenFunctionSyntax2, GenTupleParallelSyntax, GenTupleShowInstances, GenTupleMonadInstances, @@ -624,12 +625,9 @@ object Boilerplate { |package cats |package syntax | - |import cats.Functor - |import cats.Semigroupal - | |trait FunctionApplySyntax { - | implicit def catsSyntaxFunction1Apply[T, A0](f: Function1[A0, T]): Function1ApplyOps[T, A0] = new Function1ApplyOps(f) - - implicit def catsSyntaxFunction${arity}Apply[T, ${`A..N`}](f: $function): Function${arity}ApplyOps[T, ${`A..N`}] = new Function${arity}ApplyOps(f) + | def catsSyntaxFunction1Apply[T, A0](f: Function1[A0, T]): Function1ApplyOps[T, A0] = new Function1ApplyOps(f) + - def catsSyntaxFunction${arity}Apply[T, ${`A..N`}](f: $function): Function${arity}ApplyOps[T, ${`A..N`}] = new Function${arity}ApplyOps(f) |} | |private[syntax] final class Function1ApplyOps[T, A0](private val f: Function1[A0, T]) extends AnyVal with Serializable { @@ -644,4 +642,38 @@ object Boilerplate { """ } } + + object GenFunctionSyntax2 extends Template { + def filename(root: File) = root / "cats" / "syntax" / "FunctionApplySyntax2.scala" + + override def range = 2 to maxArity + + def content(tv: TemplateVals) = { + import tv._ + + val function = s"Function$arity[${`A..N`}, T]" + + val typedParams = synVals.zip(synTypes).map { case (v, t) => s"$v: F[$t]" }.mkString(", ") + + block""" + |package cats + |package syntax + | + |trait FunctionApplySyntax2 { + | implicit def catsSyntaxFunction1Apply2[T, A0](f: Function1[A0, T]): Function1ApplyOps2[T, A0] = new Function1ApplyOps2(f) + - implicit def catsSyntaxFunction${arity}Apply2[T, ${`A..N`}](f: $function): Function${arity}ApplyOps2[T, ${`A..N`}] = new Function${arity}ApplyOps2(f) + |} + | + |private[syntax] final class Function1ApplyOps2[T, A0](private val f: Function1[A0, T]) extends AnyVal with Serializable { + | def liftN[F[_]: Functor](a0: F[A0]): F[T] = Functor[F].map(a0)(f) + | def parLiftN[F[_]: Functor](a0: F[A0]): F[T] = Functor[F].map(a0)(f) + |} + | + -private[syntax] final class Function${arity}ApplyOps2[T, ${`A..N`}](private val f: $function) extends AnyVal with Serializable { + - def liftN[F[_]: Functor: Semigroupal]($typedParams): F[T] = Semigroupal.map$arity(${`a..n`})(f) + - def parLiftN[F[_]: NonEmptyParallel]($typedParams): F[T] = Parallel.parMap$arity(${`a..n`})(f) + -} + """ + } + } } diff --git a/tests/shared/src/test/scala/cats/tests/SyntaxSuite.scala b/tests/shared/src/test/scala/cats/tests/SyntaxSuite.scala index 2b7f19277d..53ff1c14b0 100644 --- a/tests/shared/src/test/scala/cats/tests/SyntaxSuite.scala +++ b/tests/shared/src/test/scala/cats/tests/SyntaxSuite.scala @@ -345,6 +345,30 @@ object SyntaxSuite { result3: F[T] } + def testParLiftNNonEmpty[F[_]: NonEmptyParallel: Functor, A, B, C, T] = { + val fa = mock[F[A]] + val fb = mock[F[B]] + val fc = mock[F[C]] + + val fapply1 = mock[A => T] + + val result1 = fapply1.parLiftN(fa) + + result1: F[T] + + val fapply2 = mock[(A, B) => T] + + val result2 = fapply2.parLiftN(fa, fb) + + result2: F[T] + + val fapply3 = mock[(A, B, C) => T] + + val result3 = fapply3.parLiftN(fa, fb, fc) + + result3: F[T] + } + def testParallelBi[M[_], F[_], T[_, _]: Bitraverse, A, B, C, D](implicit P: Parallel.Aux[M, F]): Unit = { val tab = mock[T[A, B]] val f = mock[A => M[C]]