[英]parSequence and parTraverse in tagless final
Using tagless final (without using IO, but rather a generic F) how can I abstract over something like this:使用无标签最终(不使用 IO,而是使用通用 F)我如何抽象这样的东西:
def doSomething(s: String): IO[Unit] = ???
List("authMethods", "secretEngines", "plugins", "CAs", "common").parTraverse(doSomething)
The closest I can get is using parTraverseN
from the Concurrent object, but I assume this will run concurrently instead of in parallel (as in parallelism ).我能得到的最接近的是使用来自 Concurrent
parTraverseN
的 parTraverseN,但我认为这将同时运行而不是并行运行(如并行)。 It also forces me to choose an n
where as parTraverse
does not.它还迫使我选择一个
n
,而parTraverse
没有。
The size of the list is just an example, it could be way bigger.列表的大小只是一个例子,它可能会更大。
doSomething
is a pure function, multiple executions of it can run in parallel without problems. doSomething
是一个纯 function,它的多次执行可以并行运行而不会出现问题。
Ideally, given that doSomething
returns IO[Unit]
I would like to abstract over parTraverse_
to an F
with the correct typeclass instance.理想情况下,鉴于
doSomething
返回IO[Unit]
,我想将parTraverse_
抽象为具有正确类型类实例的F
Here's a similar complete working example:这是一个类似的完整工作示例:
import cats.Applicative
import cats.instances.list._
import cats.syntax.foldable._
trait Service[F[_]] {
val items = List("authMethods", "secretEngines", "plugins", "CAs", "common")
def doSomething(s: String): F[Unit] = ???
def result(implicit F: Applicative[F]): F[Unit] =
items.traverse_(doSomething)
}
If you want to use parTraverse_
here, the minimal changes necessary would look something like this:如果您想在此处使用
parTraverse_
,则所需的最小更改将如下所示:
import cats.{Applicative, Parallel}
import cats.instances.list._
import cats.syntax.parallel._
trait Service[F[_]] {
val items = List("authMethods", "secretEngines", "plugins", "CAs", "common")
def doSomething(s: String): F[Unit] = ???
def result(implicit F: Applicative[F], P: Parallel[F]): F[Unit] =
items.parTraverse_(doSomething)
}
Alternatively you could use Parallel.parTraverse_(items)(doSomething)
and skip the syntax
import.或者,您可以使用
Parallel.parTraverse_(items)(doSomething)
并跳过syntax
导入。 Both approaches require a Foldable
instance for List
(provided here by the cats.instances.list._
import, which will no longer be necessary in Cats 2.2.0 ), and a Parallel
instance for F
, which you get via the P
constraint.这两种方法都需要
List
的Foldable
实例(此处由cats.instances.list._
导入提供,在Cats 2.2.0中不再需要),以及F
的Parallel
实例,您可以通过P
约束获得。
(Note that the Applicative
constraint on result
is no longer necessary in the second version, but that's only because this is a very simple example—I'm assuming your real code relies on something like Sync
instead, and will need both that and Parallel
.) (请注意,在第二个版本中不再需要对
result
的Applicative
约束,但这只是因为这是一个非常简单的示例——我假设您的真实代码依赖于Sync
之类的东西,并且需要它和Parallel
。 )
This answer needs a couple of footnotes, though.不过,这个答案需要几个脚注。 The first is that it might not actually be a good thing that
parTraverse_
doesn't make you specify a bound in the way that parTraverseN
does, and may result in excessive memory use, etc. (but this will depend on eg the expected size of your lists and the kind of work doSomething
is doing, and is probably outside the scope of the question).首先是
parTraverse_
不会让您以parTraverseN
的方式指定边界实际上可能不是一件好事,并且可能导致过度使用 memory 等(但这将取决于例如预期的大小您的列表和doSomething
正在做的工作,可能不在问题的 scope 范围内)。
The second footnote is that "parallel" in the sense of the Parallel
type class is more general than the "parallel" in the parallel-vs.-concurrent distinction in the Cats "Concurrency Basics" document.第二个脚注是
Parallel
类型 class 意义上的“并行”比 Cats“并发基础”文档中的并行与并发区别中的“并行”更普遍。 The Parallel
type class models a very generic kind of logical parallelism that also encompasses error accumulation , for example.例如,
Parallel
类型 class 模拟了一种非常通用的逻辑并行性,它也包含错误累积。 So when you write:所以当你写:
I assume this will run concurrently instead of in parallel (as in parallelism ).
我假设这将同时运行而不是并行运行(如并行)。
…your assumption is correct, but not exactly because the parTraverseN
method is on Concurrent
instead of Parallel
; …您的假设是正确的,但不完全是因为
parTraverseN
方法是Concurrent
而不是Parallel
; note that Concurrent.parTraverseN
still requires a Parallel
instance.注意
Concurrent.parTraverseN
仍然需要一个Parallel
实例。 When you see par
or the Parallel
type class in the context of cats.effect.Concurrent
, you should think of concurrency, not "parallelism" in the "Concurrency Basics" sense.当您在 cat.effect.Concurrent 的上下文中看到
par
或Parallel
类型cats.effect.Concurrent
时,您应该想到并发,而不是“并发基础”意义上的“并行”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.