我有一個應用程序可以對不同的後端系統進行大量調用,希望能夠使用理解來簡化後端系統中的流程。將EitherT和Future結合起來
我期待結合EitherT(scalaz)和Future(scala 2.10),這樣我就可以捕獲第一個潛在錯誤(其未來或後端系統問題),並向最終用戶返回適當的消息。我已經快速查看了一個scalaz驗證,但是捕獲第一個錯誤而不是所有錯誤的建議是使用EitherT。
我想在REPL一個簡單的例子,第一個,但我發現了以下錯誤
錯誤:無法找到參數F隱含值:scalaz.Functor [scala.concurrent.Future]
import scala.concurrent._
import scalaz._
import Scalaz._
import ExecutionContext.Implicits.global
type EitherFuture[+A] = EitherT[Future, String, A]
def method1Success : EitherFuture[Int] = {
println("method 1 success")
EitherT {
Future {
1.right
}
}
}
def method2Failure : EitherFuture[Int] = {
println("method 2 failure")
EitherT {
Future {
"fail".left
}
}
}
val m1 = method1Success
// problem
m1.isRight
// problem
def methodChain1 = {
for {
a <- method1Success
b <- method2Failure
} yield b
}
我對scala和scalaz都很陌生,所以任何指針都會很棒。
** **更新
通過包括基於@stew建議scalaz-contrib請我現在有一個更新的版本顯示,內涵與合併EitherT和未來呈現不同的簡單的用例後端的成功,後端失敗,以及未來失敗
import scala.concurrent._
import scalaz._
import Scalaz._
import ExecutionContext.Implicits.global
import scalaz.contrib._
import scalaz.contrib.std._
import scala.concurrent.duration._
type EitherFuture[+A] = EitherT[Future, String, A]
// various methods that mimic success or different failures
def methodBackendSuccess : EitherFuture[Int] = {
println("method backend success")
EitherT {
Future {1.right}
}
}
def methodBackendFailure : EitherFuture[Int] = {
println("method backend failure")
EitherT {
Future { "fail".left}
}
}
def methodFutureFailure : EitherFuture[Int] = {
println("method future failure")
EitherT {
Future.failed(new Exception("future failed"))
}
}
// different combinations for for-comprehensions
def methodChainBackendSuccess = {
for {
a <- methodBackendSuccess
b <- methodBackendSuccess
c <- methodBackendSuccess
} yield c
}
def methodChainBackendFailure = {
for {
a <- methodBackendSuccess
b <- methodBackendFailure
c <- methodBackendSuccess
} yield c
}
def methodChainFutureFailure = {
for {
a <- methodBackendSuccess
b <- methodFutureFailure
c <- methodBackendSuccess
} yield c
}
// process results for different chain methods
def processOutcome(chainMethod: => EitherFuture[Int]):Int = try {
val x = Await.result(chainMethod.run, 30 seconds)
x.toEither match {
case Left(l) => {
println("Backend failure <" + l + ">")
-1
}
case Right(r) => {
println("Backend success <" + r + ">")
r
}
}
} catch {
case e: Exception => {
println("Future error <" + e.getMessage + ">")
-99
}
}
// run tests
val backendSuccess = processOutcome(methodChainBackendSuccess)
val backendFailure = processOutcome(methodChainBackendFailure)
val futureFailure = processOutcome(methodChainFutureFailure)
你確定你需要'Either'嗎? 「未來」已經可以模擬失敗,並且排序具有您想要的行爲。 –
Hi @TravisBrown我仍然對scala很感興趣,所以你可能是正確的,我需要的是能夠捕獲後端成功,後端失敗和未來失敗,並以不同的方式處理它們。我現在已經有了一些可行的代碼,我會更新原始問題,也許這可能會讓我更清楚是否需要組合EitherT和Future。 –
有一件事花了我一段時間:Functor [Future]只能在隱式執行上下文中找到 – cvogt