问题描述
我注意到,即使在效果最强的类型类Parallel
上,cats-effect类型类层次结构也不会从cats核心继承ConcurrentEffect
。仅当您直接使用IO时,才为并行提供唯一的实例。
但是不应该有一个吗?我觉得Sync[F]
和Async[F]
应该是Parallel[F]
的好组合。
解决方法
Parallel
行为与Sync
和Async
层次结构所承诺的(实际上是顺序执行,但(a)同步执行)确实不同。 ConcurrentEffect
保证您的计算在线程池上运行,并且可以被取消(+较小元素所保证的所有内容)-仍无法启用组合并行计算,但允许您实现竞争。 Parallel
是正交语义,这就是为什么将其作为单独的类型类/类型约束进行传递的原因。因此,只需将其添加为单独的类型约束即可。
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)
}
如果您无法实例化Parallel[IO]
,请记住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 { (_,_,_) => () }