使用 ZIO 在 Scala 中组合多个期货和期权

Composing Multiple Futures and Option in Scala with ZIO

我刚刚开始评估 ZIO 以改进我的异步 Scala 代码的编程模型和性能。在我的代码库中,我经常处理 Future[Option[T]],到目前为止,我已经使用 Scalaz 的 OptionT monad 转换器来处理它。现在我想用 ZIO 试试这个。

考虑两个函数:

def foo: String => Future[Option[T]]def bar: T => Future[U]

我试过这样的事情:

val t = for {
       o: Option[Int] <- ZIO.fromFuture { implicit ec =>
            foo("test")
       }
       i: Int <- ZIO.fromOption(o)
       s: String <- ZIO.fromFuture { implicit ec =>
            bar(i)
       }
} yield s

根据我的 IDE,t 在这种情况下属于 ZIO[Any, Any, String] 类型。我不知道该怎么办。

我想考虑三种可能:

我不确定如何使用 ZIO 解析这种情况下的这些可能性。感谢任何帮助。

ZIO.fromOption(o) is IO[Unit, A] which is ZIO[Any, Unit, A], whilst the type of ZIO.fromFuture is Task[A] which is ZIO[Any, Throwable, A], as documented by Type Aliases 的类型。因此类型不对齐

ZIO[Any, Unit, A]
ZIO[Any, Throwable, A]

尝试 mapError 将错误类型与 Throwable 对齐,就像这样

for {
  o <- ZIO.fromFuture { implicit ec => foo("test") }
  i <- ZIO.fromOption(o).mapError(_ => new RuntimeException("boom"))
  s <- ZIO.fromFuture { implicit ec => bar(i)}
} yield s

在这种情况下,有几个运算符可以帮助您解决问题,基本上我建议结合使用 some 和 [,而不是使用 fromOption 显式解包 Option =14=]

val t: Task[Option[String]] = (for {

  // This moves the `None` into the error channel
  i: Int <- ZIO.fromFuture(implicit ec => foo("test")).some

  // This wraps the error in a Some() so that the signature matches
  s: String <- ZIO.fromFuture(implicit ec => bar(i)).asSomeError

} yield s).optional // Unwraps the None back into the value channel