1

我刚刚开始评估 ZIO 以改进我的异步 Scala 代码的编程模型和性能。在我的代码库中,我Future[Option[T]]经常处理,到目前为止,我已经使用 Scalaz 的OptionTmonad 转换器处理了这个问题。现在我想用 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]我不知道该怎么办。

我想考虑三种可能性:

  • foo产生一个Some可以与值上的其他函数组合的“成功”案例
  • foo产生一个的情况None
  • 任一函数产生错误的情况

我不确定如何使用 ZIO 在这种情况下解析这些可能性。任何帮助表示赞赏。

4

2 回答 2

2

的类型ZIO.fromOption(o)IO[Unit, A]哪个是ZIO[Any, Unit, A],而类型ZIO.fromFutureTask[A]哪个是ZIO[Any, Throwable, A],如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
于 2020-04-05T17:00:26.000 回答
1

在这种情况下,有几个运算符可以帮助您,基本上不是显式地解开Optionwith fromOption,我建议使用some和的组合asSomeError

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
于 2020-04-06T03:45:48.737 回答