Can there be Parallel for Async in cats effect?

Viewed 340

I noticed that cats-effect typeclass hierarchy doesn't inherit Parallel from cats core even at their most powerful typeclass ConcurrentEffect. The only instance provided for parallel exists only if you use IO directly.

But shouldn't there be one? I kinda feel like Sync[F] and Async[F] should be a nice duo for Parallel[F].

1 Answers

The Parallel behavior is really different to what Sync and Async hierarchy promises (that is sequential but (a)synchronous execution). ConcurrentEffect promises that your computation runs on a thread pool and can be cancelled (+ everything its smaller elements promise) - still not enable combining parallel computations but allows you to implement races. Parallel is an orthogonal semantics which is why it is passed as a separate type class/type constraint. So just add it as a separate type constraint.

def toStringParallel[F[_]: Sync: Parallel](list: List[F[Int]]): F[List[String]] =
  list.parTraverse(a => a.toString.pure[F])

object App1 extends IOApp {
  def run(args: List[String]) = toStringParallel[IO](List(IO(1), IO(2)))
    .as(ExitCode.Success)
}

If you cannot instantiate Parallel[IO], remember that it requires ContextShift[IO] to create an instant of Parallel[IO].

// example from docs
implicit val contextShift: ContextShift[IO] = IO.contextShift(ExecutionContext.global)

val ioA = IO(println("Running ioA"))
val ioB = IO(println("Running ioB"))
val ioC = IO(println("Running ioC"))

// make sure that you have an implicit ContextShift[IO] in scope. 
val program = (ioA, ioB, ioC).parMapN { (_, _, _) => () }
Related