scala future scalaz for-comprehension scalaz7

scala - Combinando EitherT y Future



scalaz for-comprehension (2)

Debe importar o proporcionar una instancia de Functor para el futuro. Recomiendo usar el del proyecto scalaz-contrib . -contrib es un proyecto separado en el que trabajaron las mismas personas que trabajan en scalaz. Las instancias Futuras están en este paquete en lugar de scalaz-core porque scalaz-core, por ahora, mantiene la compatibilidad entre scala 2.9 y 2.10.

Tengo una aplicación que hace muchas llamadas a diferentes sistemas de back-end, y espero utilizar las comprensiones para simplificar el flujo del proceso a través de los sistemas de back-end.

Estoy buscando combinar EitherT (scalaz) y Future (scala 2.10) para poder capturar el primer error potencial (donde es un problema futuro o del sistema backend) y devolver un mensaje apropiado al usuario final. He echado un vistazo rápido a Validation scalaz pero la recomendación para capturar el primer error y no todos los errores es usar EitherT.

Estoy probando un ejemplo simple en REPL primero, pero obtengo el siguiente error

error: no se pudo encontrar el valor implícito para el parámetro 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 }

Todavía soy nuevo tanto en scala como en scalaz, por lo que cualquier puntero sería genial.

** Actualización **

Al incluir scalaz-contrib en base a la sugerencia de @stew, ahora tengo una versión actualizada que muestra las comprensiones con la combinación de EitherT y Future que muestra diferentes casos de uso simple éxito de back-end, falla de backend y falla futura

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)


Mire la firma de isRight definida en EitherT:

def isRight(implicit F: Functor[F]): F[Boolean]

Está esperando un Functor parametrizado con el parámetro de tipo de su EitherT, en su caso Futuro. Scalaz no proporciona un Functor implícito para el tipo Future, debe escribir el suyo siguiendo este modelo:

http://scalaz.github.io/scalaz/scalaz-2.9.0-1-6.0/doc.sxr/scalaz/Functor.scala.html

Observe todas las definiciones implícitas para cada tipo soportado.