我正在采用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)
}
我無法使其正常作業/編譯,請您幫我理解:
- 如果檢測到a ,如何避免執行對
load(inloadAll) 的后續呼叫Left? - 如果呼叫
load成功,我如何將其right值用于以下呼叫load? - 這是正確的方法嗎?你會以不同的方式實作它嗎?
謝謝大家
uj5u.com熱心網友回復:
讓我首先列出我認為可以滿足您的需求的代碼,以及處理此類事情的典型方式,然后我將描述內容和原因,也許還有其他一些建議:
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
}
首先,IO[Future[_]]Future 本身沒有 try-catch 內部的許多組合器,可以幫助您管理錯誤,假設您對回傳的內容有一定的控制權。
當以這種方式應用時,Scala 中的For-comprehensions是“短路”,所以如果第一次呼叫load(1)失敗并出現左,那么其余的理解將不會執行。的使用EitherT允許您管理您Either被“包裹”在效果型別中的事實。
這種方法存在一些問題,特別是在方差方面,您可以在此處閱讀有關它們的資訊:
http://www.beyondthelines.net/programming/the-problem-with-eithert/
使用這種模式還有一些性能影響,您可能需要考慮
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/347931.html
上一篇:使用IntelliJ使用sbt將Scala與Hive資料庫連接起來以獲得依賴項
下一篇:Scala模式匹配
