6

I have the next code written using Cats IO that executes multiple actions in parallel (simplified):

import cats.effect._
import cats.implicits._

import scala.concurrent.ExecutionContext.Implicits.global

    class ParallelExecIO {

        def exec: IO[List[String]] = {
            val foo = IO.shift *> IO("foo")
            val bar = IO.shift *> IO("bar")
            List(foo, bar).parSequence
        }
    }

Is it possible to rewrite this code using effect abstraction? What type evidences should be provided?

Sample:

class ParallelExecIO[F[_]: ConcurrentEffect /* ??? */] {

    def exec: F[List[String]] = {
        val foo = Async.shift[F](implicitly) *> "foo".pure[F]
        val bar = Async.shift[F](implicitly) *> "bar".pure[F]
        List(foo, bar).parSequence 
    }
}

[error] value parSequence is not a member of List[F[String]]

Alexey Sirenko
  • 452
  • 3
  • 12

1 Answers1

4

With

scalaVersion := "2.12.5"
scalacOptions += "-Ypartial-unification"
libraryDependencies += "org.typelevel" %% "cats-core" % "1.1.0"
libraryDependencies += "org.typelevel" %% "cats-effect" % "0.10"

the error is

Error:(23, 22) could not find implicit value for parameter P: cats.Parallel[F,F]
      List(foo, bar).parSequence

So try

import cats.Parallel
import cats.effect.{Async, ConcurrentEffect}
import cats.implicits._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.language.higherKinds

class ParallelExecIO[F[_]: ConcurrentEffect, G[_]](implicit ev: Parallel[F, G]) {

  def exec: F[List[String]] = {
    val foo = Async.shift[F](implicitly) *> "foo".pure[F]
    val bar = Async.shift[F](implicitly) *> "bar".pure[F]
    List(foo, bar).parSequence
  }
}

Surely you can introduce type Parallel[F[_]] = cats.Parallel[F, F] and then this can be rewritten as class ParallelExecIO[F[_]: ConcurrentEffect : Parallel] {...

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • Thanks, rewritten class compiles although my IntelliJ marks `parSequence` red. But there is a problem with class instantiation. ```import IO._ val pei = new ParallelExecIO[IO]()``` does not compile since new class requires evidence of type Parallel[IO, IO], but IO class provides implicit evidence `IO.ioParallel` of type `Parallel[IO, IO.Par]`. Should evidence type be fixed? https://github.com/typelevel/cats-effect/blob/master/core/shared/src/main/scala/cats/effect/IO.scala#L723 – Alexey Sirenko May 08 '18 at 19:24
  • 1
    Try `class ParallelExecIO[F[_]: ConcurrentEffect, G[_]](implicit ev: Parallel[F, G]) {...` `import IO._` `val pei = new ParallelExecIO` – Dmytro Mitin May 08 '18 at 19:44