Skip to content
Merged
48 changes: 45 additions & 3 deletions core/src/main/scala/cats/syntax/parallel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,24 @@ trait ParallelSyntax extends TupleParallelSyntax {
implicit final def catsSyntaxParallelSequence1[T[_]: Traverse, M[_], A](tma: T[M[A]]): ParallelSequenceOps1[T, M, A] =
new ParallelSequenceOps1(tma)

implicit final def catsSyntaxParallelAp[M[_]: FlatMap, A](ma: M[A]): ParallelApOps[M, A] =
@deprecated("Kept for binary compatibility", "2.8.0")
final def catsSyntaxParallelAp[M[_]: FlatMap, A](ma: M[A]): ParallelApOps[M, A] =
new ParallelApOps(ma)

implicit final def catsSyntaxParallelAp1[M[_], A](ma: M[A]): ParallelApOps1[M, A] =
new ParallelApOps1(ma)

implicit final def catsSyntaxNonEmptyParallelAp[M[_], A](ma: M[A]): NonEmptyParallelApOps[M, A] =
new NonEmptyParallelApOps(ma)
}

trait ParallelApplySyntax {
implicit final def catsSyntaxParallelApply[F[_], A, B](fa: F[A => B]): ParallelApplyOps[F, A, B] =
@deprecated("Kept for binary compatibility", "2.8.0")
final def catsSyntaxParallelApply[F[_], A, B](fa: F[A => B]): ParallelApplyOps[F, A, B] =
new ParallelApplyOps(fa)

implicit final def catsSyntaxNonEmptyParallelApply[F[_], A, B](fa: F[A => B]): NonEmptyParallelApplyOps[F, A, B] =
new NonEmptyParallelApplyOps(fa)
}

trait ParallelFlatSyntax {
Expand Down Expand Up @@ -258,8 +269,8 @@ final class ParallelUnorderedFlatSequenceOps[T[_], M[_], A](private val tmta: T[
Parallel.parUnorderedFlatSequence(tmta)
}

@deprecated("Kept for binary compatibility", "2.8.0")
final class ParallelApOps[M[_], A](private val ma: M[A]) extends AnyVal {

def &>[B](mb: M[B])(implicit P: Parallel[M]): M[B] =
P.parProductR(ma)(mb)

Expand All @@ -279,6 +290,29 @@ final class ParallelApOps[M[_], A](private val ma: M[A]) extends AnyVal {
Parallel.parReplicateA(n, ma)
}

final class ParallelApOps1[M[_], A](private val ma: M[A]) extends AnyVal {
def parReplicateA(n: Int)(implicit P: Parallel[M]): M[List[A]] =
Parallel.parReplicateA(n, ma)
}

final class NonEmptyParallelApOps[M[_], A](private val ma: M[A]) extends AnyVal {
def &>[B](mb: M[B])(implicit P: NonEmptyParallel[M]): M[B] =
P.parProductR[A, B](ma)(mb)

def <&[B](mb: M[B])(implicit P: NonEmptyParallel[M]): M[A] =
P.parProductL[A, B](ma)(mb)

def parProductL[B](mb: M[B])(implicit P: NonEmptyParallel[M]): M[A] =
P.parProductL[A, B](ma)(mb)

def parProductR[B](mb: M[B])(implicit P: NonEmptyParallel[M]): M[B] =
P.parProductR[A, B](ma)(mb)

def parProduct[B](mb: M[B])(implicit P: NonEmptyParallel[M]): M[(A, B)] =
Parallel.parProduct(ma, mb)
}

@deprecated("Kept for binary compatibility", "2.8.0")
final class ParallelApplyOps[M[_], A, B](private val mab: M[A => B]) extends AnyVal {
def <&>(ma: M[A])(implicit P: Parallel[M]): M[B] =
Parallel.parAp(mab)(ma)(P)
Expand All @@ -287,6 +321,14 @@ final class ParallelApplyOps[M[_], A, B](private val mab: M[A => B]) extends Any
Parallel.parAp(mab)(ma)
}

final class NonEmptyParallelApplyOps[M[_], A, B](private val mab: M[A => B]) extends AnyVal {
def <&>(ma: M[A])(implicit P: NonEmptyParallel[M]): M[B] =
Parallel.parAp[M, A, B](mab)(ma)(P)

def parAp(ma: M[A])(implicit P: NonEmptyParallel[M]): M[B] =
Parallel.parAp[M, A, B](mab)(ma)
}

final class ParallelBitraverseOps[T[_, _], A, B](private val tab: T[A, B]) extends AnyVal {
def parBitraverse[M[_], C, D](f: A => M[C], g: B => M[D])(implicit T: Bitraverse[T], P: Parallel[M]): M[T[C, D]] =
Parallel.parBitraverse(tab)(f, g)
Expand Down
9 changes: 7 additions & 2 deletions tests/shared/src/test/scala/cats/tests/SyntaxSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,20 @@ object SyntaxSuite {
val gunit: G[F[A]] = fga.nonEmptySequence
}

def testParallel[M[_]: Monad, F[_], T[_]: Traverse, A, B](implicit P: Parallel.Aux[M, F]): Unit = {
def testParallel[M[_]: Parallel, T[_]: Traverse, A, B]: Unit = {
val ta = mock[T[A]]
val f = mock[A => M[B]]
val mtb = ta.parTraverse(f)

val tma = mock[T[M[A]]]
val mta = tma.parSequence

val ma = mock[M[A]]

val mla: M[List[A]] = ma.parReplicateA(mock[Int])
}

def testNonEmptyParallel[M[_]: NonEmptyParallel, A, B]: Unit = {
val ma = mock[M[A]]
val mb = mock[M[B]]

Expand All @@ -205,7 +211,6 @@ object SyntaxSuite {
val mb4: M[B] = ma.parProductR(mb)
val mab2: M[(A, B)] = ma.parProduct(mb)
val mb5: M[B] = mab.parAp(ma)
val mla: M[List[A]] = ma.parReplicateA(mock[Int])
}

def testParallelUnorderedTraverse[M[_]: Monad, F[_]: CommutativeApplicative, T[_]: UnorderedTraverse: FlatMap, A, B](
Expand Down