大叔,把Seq[ZIO]改成ZIO[Seq]

Zio, transform Seq[ZIO] to ZIO[Seq]

这可能是个愚蠢的问题,但从 ZIO 开始,我无法将 Seq[ZIO] 转换为 ZIO[Seq]:

def translate(keys: Seq[String], locales: Seq[Locale]):RIO[Translator, Seq[Translation]] = {
  for {
    service <- ZIO.environment[Translator]
  } yield {
    // service.translate produce a zio.Task[Translation]
    keys.map(k => service.translate(k, locales)
  }
}

Required: RIO[Translator, Seq[Translation]]

Found : ZIO[Translator, Nothing, Seq[zio.Task[Translation]]

我尝试了 flatMapflattencollectAllmerge,但我无法与任何人取得预期的结果。

如何将 Seq[ZIO[_, _, B]] 转换为 ZIO[_, _, Seq[B]]

谢谢

编辑: 似乎 ZIO.foreach 是最好的选择,但是由于 for comprehension,我仍然将它包裹在另一个 ZIO 中。

如果我没看错,你可以使用 cats:

中的 traverse 函数来完成
import cats.instances.list._
import cats.syntax.traverse._
import zio.{RIO, Task, ZIO}
import zio.interop.catz._

import java.util.Locale

case class Translation()
trait Translator {
  def translate(k: String, locales: Seq[Locale]): Task[Translation]
}

def translate(keys: Seq[String], locales: Seq[Locale]): RIO[Translator, Seq[Translation]] = {
  val translator: Translator = ???
  for {
    service <- ZIO.effect(translator)
    result  <- keys.toList.traverse(k => service.translate(k, locales))
  } yield result
}

对于 List[ZIO[_, _, B]]ZIO[_, _, List[B]] 的映射,您可以使用 sequence 函数,我建议为此使用 cats 库。

import zio.ZIO
import zio.interop.catz._
import cats.syntax.traverse._
import cats.instances.list._

def ziosSequence[B](seqZIO: Seq[ZIO[Any, Throwable, B]]): ZIO[Any, Throwable, Seq[B]] = 
  seqZIO.toList.sequence.map(_.toSeq)

sequence 签名是:

def sequence[G[_]: Applicative, A](fga: F[G[A]]): G[F[A]] =
  traverse(fga)(ga => ga)

在这里我们看到什么功能做我们需要的。 它需要 GApplicative 实例(G 在您的情况下是 ZIO),我们只需使用 import zio.interop.catz._ 导入它 此外,为了使列表能够调用 sequence,我们需要为 List 导入 Traverse 实例: 通过 import cats.instances.list._ 不幸的是,我们不能用 Seq 做同样的技巧,因为我们需要 sequenceTraverse 实例,我们应该在和之前来回转换 SeqListsequence.

之后

有用的链接:

因为 for 循环转换为 flatMap 除了最后一行是 map,你想添加 foreach 调用 within ] for循环。

def translate(keys: Seq[String], locales: Seq[Locale]): RIO[Translator, Seq[Translation]] = { 
  for {
    translator <- ZIO.environment[Translator]
    translations <- ZIO.foreach(keys)(translator.translate(_, locales))
  } yield translations
}