同様の完全な動作例を次に示します。
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 2.2.0cats.instances.list._
では不要になります) と、制約を介して取得する のインスタンスが必要です。Parallel
F
P
Applicative
(2 番目のバージョンではon の制約result
が不要になっていることに注意してください。ただし、これは単にこれが非常に単純な例であるためです。実際のコードはSync
代わりに のようなものに依存しており、それと の両方が必要になると想定していますParallel
。)
ただし、この回答にはいくつかの脚注が必要です。parTraverse_
1つ目は、境界を指定する方法で境界を指定しないことは実際には良いことではないparTraverseN
可能性があり、過度のメモリ使用などを引き起こす可能性があることです.作業の種類doSomething
は行っており、おそらく質問の範囲外です)。
2 番目の脚注は、Parallel
型クラスの意味での「並列」は、Cats の「同時実行の基本」ドキュメントの並列と同時の区別における「並列」よりも一般的であるということです。型クラスは、たとえば、エラー累積Parallel
も含む非常に一般的な種類の論理的並列処理をモデル化します。だからあなたが書くとき:
これは、並列ではなく同時に実行されると思います(parallelismのように)。
…あなたの仮定は正しいですが、parTraverseN
メソッドが;Concurrent
の代わりにon であるため、正確ではありません。まだインスタンスが必要であるParallel
ことに注意してください。または のコンテキストで型クラスを見るときは、「並行処理の基本」の意味での「並列処理」ではなく、並行処理について考える必要があります。Concurrent.parTraverseN
Parallel
par
Parallel
cats.effect.Concurrent