Вот аналогичный полный рабочий пример:
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)
}
Если вы хотите использовать здесь 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)
}
В качестве альтернативы вы можно использовать Parallel.parTraverse_(items)(doSomething)
и пропустить импорт syntax
. Для обоих подходов требуется экземпляр Foldable
для List
(предоставленный здесь импортом cats.instances.list._
, который больше не потребуется в Cats 2.2.0 ), и экземпляр Parallel
для F
, который вы получаете через ограничение P
.
(Обратите внимание, что ограничение Applicative
на result
больше не требуется во второй версии, но это только потому, что это очень простой пример - Я предполагаю, что ваш реальный код полагается на что-то вроде Sync
, и ему понадобится и это, и Parallel
.)
Однако для этого ответа нужна пара сносок. Во-первых, это может быть не очень хорошо, что parTraverse_
не заставляет вас указывать привязку, как это делает parTraverseN
, и может привести к чрезмерному использованию памяти, et c. (но это будет зависеть, например, от ожидаемого размера ваших списков и вида работы, которую выполняет doSomething
, и, вероятно, выходит за рамки вопроса).
Вторая сноска - это «параллель» в Смысл класса типа Parallel
является более общим, чем «параллель» в различении параллельного и параллельного в документе Cats «Основы параллелизма». Класс типа Parallel
моделирует очень общий тип логического параллелизма c, который также включает, например, накопление ошибок . Поэтому, когда вы пишете:
, я предполагаю, что это будет работать одновременно, а не параллельно (как в parallelism ).
... ваше предположение верно , но не совсем потому, что метод parTraverseN
находится на Concurrent
вместо Parallel
; обратите внимание, что для Concurrent.parTraverseN
по-прежнему требуется экземпляр Parallel
. Когда вы видите par
или класс типов Parallel
в контексте cats.effect.Concurrent
, вы должны думать о параллелизме, а не о «параллелизме» в смысле «Основы параллелизма».