我正在采用IO/在适用的情况下Either替换Future/ Exception,但我需要以下代码的帮助:
// some Java library
def dbLoad(id: Int): Int = {
throw new Exception("db exception")
}
// my scala code
sealed trait DbError extends Exception with Product
object DbError {
case object SomeError extends DbError
}
val load: Int => IO[Either[DbError, Int]] = { id =>
IO.fromFuture { IO { Future {
try { Right(dbLoad(id)) } catch { case NonFatal(e) => Left(SomeError) }
} } }
}
val loadAll: IO[Either[DbError, (Int, Int, Int)]] =
for {
i1 <- load(1)
i2 <- // call 'load' passing i1 as parameter, if i1 is 'right'
i3 <- // call 'load' passing i2 as parameter, if i2 is 'right'
} yield (i1, i2, i3) match {
case (Right(i1), Right(i2), Right(i3)) => Right((i1, i2, i3))
case _ => Left(SomeError)
}
Run Code Online (Sandbox Code Playgroud)
我无法让它正常工作/编译,你能帮我理解吗:
load(in ) 的后续调用?loadAllLeftload成功,我如何将其right值用于以下调用load?感谢大家
首先让我列出我认为可以满足您想要的内容的代码,以及通常如何处理此类事情,然后我将描述内容和原因,也许还有一些其他建议:
import cats.data.EitherT
import cats.effect.IO
import cats.implicits._
import com.example.StackOverflow.DbError.SomeError
import scala.concurrent.Future
import scala.util.control.NonFatal
import scala.concurrent.ExecutionContext.Implicits.global
object StackOverflow {
// some Java library
def dbLoad(id: Int): Int = {
throw new Exception("db exception")
}
// my scala code
sealed trait DbError extends Exception with Product
object DbError {
case object SomeError extends DbError
}
val load: Int => IO[Either[DbError, Int]] = { id =>
IO.fromFuture(
IO(
Future(dbLoad(id))
.map(Right(_))
.recover {
case NonFatal(_) => Left(SomeError)
}
)
)
}
val loadAll: EitherT[IO, DbError, (Int, Int, Int)] =
for {
i1 <- EitherT(load(1))
i2 <- EitherT(load(i1))
i3 <- EitherT(load(i2))
} yield (i1, i2, i3)
val x: IO[Either[DbError, (Int, Int, Int)]] = loadAll.value
}
Run Code Online (Sandbox Code Playgroud)
IO[Future[_]]首先, Future 本身有许多组合器,可以帮助您管理错误,而不是在 内部使用 try-catch,前提是您对返回的内容有一定的控制权。
Scala 中的For 推导式以这种方式应用时会“短路”,因此如果第一次调用load(1)因左而失败,则推导式的其余部分将不会执行。使用可以让您管理“包裹”在效果类型中EitherT的事实。Either
这种方法存在一些问题,特别是关于方差的问题,您可以在此处阅读相关内容:
http://www.beyondthelines.net/programming/the-problem-with-eithert/
您可能需要考虑使用此模式对性能的一些影响