问题描述
这可能是一个愚蠢的问题,但从 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)
}
}
必需:RIO[Translator,Seq[Translation]]
找到:ZIO[Translator,nothing,Seq[zio.Task[Translation]]
我尝试了 flatMap
、flatten
、collectAll
和 merge
,但我无法与任何人取得预期的结果。
如何将 Seq[ZIO[_,_,B]]
转换为 ZIO[_,Seq[B]]
?
谢谢
编辑: ZIO.foreach
似乎是最好的选择,但是由于理解的原因,我仍然将它包裹在另一个 ZIO 中。
解决方法
因为除了最后一行是 flatMap
之外,for 循环转换为 map
,所以您想在 for 循环中添加 foreach
调用 .
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
}
,
如果我猜对了,您可以使用 traverse
中的 cats
函数:
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],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,Seq[B]] =
seqZIO.toList.sequence.map(_.toSeq)
sequence
签名是:
def sequence[G[_]: Applicative,A](fga: F[G[A]]): G[F[A]] =
traverse(fga)(ga => ga)
在这里我们看到什么函数做我们需要的。
它需要 Applicative
的 G
实例(在您的情况下,G
是 ZIO
),我们只需使用 import zio.interop.catz._
导入它
此外,为了使列表能够调用 sequence
,我们需要为 Traverse
导入 List
实例:
来自import cats.instances.list._
不幸的是,我们不能用 Seq
做同样的技巧,因为我们需要 Traverse
的实例 sequence
,我们应该在之前和之前来回转换 Seq
到 List
sequence
之后。
有用的链接: