私は、さまざまなバックエンドシステムに多くの呼び出しを行い、for-comprehensionsを使用してバックエンドシステム全体のプロセスフローを簡素化することを望んでいるアプリケーションを持っています。いずれかと未来を融合する
EitherT(scalaz)とFuture(scala 2.10)を組み合わせることで、最初の潜在的なエラー(将来またはバックエンドシステムの問題がある場合)をキャプチャし、エンドユーザーに適切なメッセージを返すことができます。私はスカラズ検証をすばやく見てきましたが、最初のエラーをキャプチャするための推奨事項であり、すべてのエラーではなく、EitherTを使用することです。
私は、しかし、私は次のエラーを取得しています、最初のREPLでの簡単な例をしようとしている
エラー:scalaz.Functor [scala.concurrent.Future]
:パラメータFの暗黙的な値を見つけることができませんでした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と未来が異なるシンプルなユースケースバックエンドの成功を示す組み合わせ、バックエンドで示し更新されたバージョンを持っていますEitherTに定義されたisRight
の署名に失敗し、今後の失敗
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」ビジネスがまったく必要ですか? 'Future'はすでに失敗をモデル化することができ、シーケンスにはあなたが望む動作があります。 –
こんにちは@TravisBrown私はまだ私が必要とするかもしれないバックグラウンドの成功、バックエンドの失敗、および将来の失敗をキャプチャし、それらを別々に処理する能力があるかもしれないので、スカラの周りに頭を上げています。私は今、いくつかのコードを入手しました。元の質問を更新し、おそらくそれがEitherTとFutureの組み合わせが必要かどうかを明確にするかもしれません。 –
私はしばらく時間を要したこと:Functor [Future]は、暗黙の実行コンテキストが有効範囲内にある場合にのみ見つけることができます – cvogt