使用 Future[Validation[E,A]] 进行理解
Working with Future[Validation[E,A]] in for comprehensions
我想将 return: Validation[E,A]
的一些 API 更改为异步的,因此理想情况下:Future[Validation[E,A]]
。但是我希望能够使用这些来理解。
考虑以下示例:
import scala.concurrent.{Await, ExecutionContext, Future}
import ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scalaz.{Failure, Success, Validation}
def getName : Future[Validation[Int,String]] = {
Future{
Success("ed")
}
}
def useName(name:String) : Future[Validation[Int,String]] = {
Future{
Success(s"hi $name")
}
}
val name : Future[Validation[Int,String]] = getName.flatMap{ v =>
v match {
case Success(name) => useName(name)
case Failure(e) => Future(Failure(e))
}
}
Await.result(name, 1.second)
要获得 name
,我需要从验证中获得成功值,并使用该值调用 useName
。
有什么方法可以让我按照这些思路做一些事情:
val name : Future[Validation[Int,String]] = for{
n <- getName
b <- useName(n)
} yield b
好像我希望理解在 Future > Validation
上下文中工作。
我很乐意使用略有不同的类型,并且我考虑过仅使用 Future
本身但有例外,但我很想知道上述是否可行,而不会发生任何阻塞。
我认为唯一的方法是编写你自己的 FutureValidation
monad:
case class FutureValidation[+E, +A](futval: Future[Validation[E, A]]) {
def map[B](f: A => B)(implicit executor: ExecutionContext): FutureValidation[E, B] = {
val result = futval.map { validation =>
validation.fold(
fail => Failure(fail),
succ => Success(f(succ))
)
}
FutureValidation(result)
}
def flatMap[EE >: E, B](f: A => FutureValidation[EE, B])(implicit executor: ExecutionContext): FutureValidation[EE, B] = {
val result = futval flatMap { validation =>
validation.fold(
fail => Future(Failure(fail)),
succ => f(succ).futval
)
}
FutureValidation(result)
}
}
object FutureValidation {
def apply[E, A](validation: => Validation[E, A])(implicit executor: ExecutionContext): FutureValidation[E, A] =
apply(Future(validation))
}
然后你可以得到类似的东西:
implicit val e = ExecutionContext.global
val a = scalaz.Success("")
val b = Future(scalaz.Success(""))
for {
r1 <- FutureValidation(a)
r2 <- FutureValidation(b)
} yield r2
我想将 return: Validation[E,A]
的一些 API 更改为异步的,因此理想情况下:Future[Validation[E,A]]
。但是我希望能够使用这些来理解。
考虑以下示例:
import scala.concurrent.{Await, ExecutionContext, Future}
import ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scalaz.{Failure, Success, Validation}
def getName : Future[Validation[Int,String]] = {
Future{
Success("ed")
}
}
def useName(name:String) : Future[Validation[Int,String]] = {
Future{
Success(s"hi $name")
}
}
val name : Future[Validation[Int,String]] = getName.flatMap{ v =>
v match {
case Success(name) => useName(name)
case Failure(e) => Future(Failure(e))
}
}
Await.result(name, 1.second)
要获得 name
,我需要从验证中获得成功值,并使用该值调用 useName
。
有什么方法可以让我按照这些思路做一些事情:
val name : Future[Validation[Int,String]] = for{
n <- getName
b <- useName(n)
} yield b
好像我希望理解在 Future > Validation
上下文中工作。
我很乐意使用略有不同的类型,并且我考虑过仅使用 Future
本身但有例外,但我很想知道上述是否可行,而不会发生任何阻塞。
我认为唯一的方法是编写你自己的 FutureValidation
monad:
case class FutureValidation[+E, +A](futval: Future[Validation[E, A]]) {
def map[B](f: A => B)(implicit executor: ExecutionContext): FutureValidation[E, B] = {
val result = futval.map { validation =>
validation.fold(
fail => Failure(fail),
succ => Success(f(succ))
)
}
FutureValidation(result)
}
def flatMap[EE >: E, B](f: A => FutureValidation[EE, B])(implicit executor: ExecutionContext): FutureValidation[EE, B] = {
val result = futval flatMap { validation =>
validation.fold(
fail => Future(Failure(fail)),
succ => f(succ).futval
)
}
FutureValidation(result)
}
}
object FutureValidation {
def apply[E, A](validation: => Validation[E, A])(implicit executor: ExecutionContext): FutureValidation[E, A] =
apply(Future(validation))
}
然后你可以得到类似的东西:
implicit val e = ExecutionContext.global
val a = scalaz.Success("")
val b = Future(scalaz.Success(""))
for {
r1 <- FutureValidation(a)
r2 <- FutureValidation(b)
} yield r2