将 ZIO 任务转换为 IO

kra*_*aik 2 zio

我有下一个代码:

import zio._

import scala.concurrent.Future

case class AppError(description: String) extends Throwable
// legacy-code imitation
def method(x: Int): Task[Boolean] = {
  Task.fromFuture { implicit ec => Future.successful(x == 0) }
}

def handler(input: Int): IO[AppError, Int] = {
  for {
    result <- method(input)
    _ <- IO.fail(AppError("app error")).when(result)
  } yield input
}

Run Code Online (Sandbox Code Playgroud)

但这段代码无法编译,因为编译器说结果类型是:

ZIO[Any, Throwable, Int]

如何从Task(我调用的地方method)转换为IO?

pau*_*els 7

您需要决定如何处理Throwable那些不是的错误AppError

如果您决定要将它们映射到AppError您可以执行的操作:

method(input).mapError {
  case ae: AppError => ae
  case other =>        AppError(other.getMessage)
}
Run Code Online (Sandbox Code Playgroud)

如果您想细化这些错误并仅保留那些错误,AppError那么您可以使用运算符系列之一refine*,这将保留与谓词匹配的错误并否则终止纤程。

method(input).refineToOrDie[AppError] // IO[AppError, Boolean]
// Or
method(input).refineOrDie { case ae: AppError => ae } // IO[AppError, Boolean]
Run Code Online (Sandbox Code Playgroud)

或者,如果您想假设所有错误都method被视为“光纤终止”,那么您可以使用.orDie吸收错误并终止光纤:

method(input).orDie // UIO[Boolean]
Run Code Online (Sandbox Code Playgroud)

或者,如果您想从错误中恢复并以不同的方式处理它,那么您可以使用catch*系列

method(input).catchAll(_ => UIO.succeed(false)) // UIO[Boolean]
Run Code Online (Sandbox Code Playgroud)

最后,如果您想将结果映射到Either您可以使用的.either,这会将错误从错误通道中取出并将其映射到Either[E, A]

method(input).either // UIO[Either[Throwable, Boolean]]
Run Code Online (Sandbox Code Playgroud)

这里也有一个很棒的备忘单(尽管确实有点过时)