【问题标题】:Zio, transform Seq[ZIO] to ZIO[Seq]Zio,将 Seq[ZIO] 转换为 ZIO[Seq]
【发布时间】:2021-07-21 20:37:19
【问题描述】:

这可能是个愚蠢的问题,但从 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]]

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

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

谢谢

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

【问题讨论】:

    标签: scala zio


    【解决方案1】:

    因为除了最后一行是 map 之外,for 循环转换为 flatMap,因此您希望在 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
    }
    

    【讨论】:

      【解决方案2】:

      如果我猜对了,您可以使用 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)
      

      在这里我们可以看到我们需要什么功能。 它需要 Applicative 实例为 GG 在您的情况下是 ZIO),我们只需使用 import zio.interop.catz._ 导入它 此外,要使列表能够调用sequence,我们需要为List 导入Traverse 实例: 由import cats.instances.list._ 不幸的是,我们不能对Seq 做同样的事情,因为我们需要sequenceTraverse 实例,并且我们应该在sequence 之前和之后将Seq 转换为List

      有用的链接:

      【讨论】:

      • 这在技术上是正确的,但是为此导入整个 cats 库就有点过头了,因为 ZIO 定义了自己的组合器。
      • @francoisr 你是对的,也许只是对我来说更熟悉
      • 感谢您的快速回答。然而,正如@francoisr 所说,它看起来有点矫枉过正,我要求的是 ZIO 解决方案(虽然它可能并不明显)。
      猜你喜欢
      • 1970-01-01
      • 2020-10-22
      • 2021-07-17
      • 2021-08-04
      • 2020-11-01
      • 1970-01-01
      • 2020-01-30
      • 2019-06-16
      • 2022-12-01
      相关资源
      最近更新 更多