假设我有几个返回\/[Throwable, String]的方法。右边的值Int是我想要的,左边的值累积错误。
import scalaz._
import Scalaz._
type ErrorOr[T] = \/[Throwable, T]
def init(a: Int): ErrorOr[Int] = a.right
def add(a: Int, b: Int): ErrorOr[Int] = (a + b).right
def multiply(a: Int, b: Int): ErrorOr[Int] = (a * b).right
init(3).flatMap(add(_, 4)).flatMap(multiply(_, 3)) // 21它看起来很好,因为scalaz的平面映射是有偏向的,所以它将基于正确的值进行操作。
但是,如果要为API调用更改方法,则返回类型将为Future[ErrorOr[T]]。有什么方法可以用来返回Future[ErrorOr[T]]吗?此外,我可能希望使用future.flatMap作为回调,而不是在这里使用await来阻止
def init(a: Int): Future[ErrorOr[Int]] = Future(a.right)
def add(a: Int, b: Int): Future[ErrorOr[Int]] = Future((a + b).right)
def multiply(a: Int, b: Int): Future[ErrorOr[Int]] = Future((a * b).right)发布于 2016-02-23 19:45:11
您可以将init的结果包装在EitherT monad转换器中,使用flatMapF而不是flatMap直接使用add和multiply,然后调用run以获取Future[ErrorOr[Int]]:
EitherT(init(3)).flatMapF(add(_, 4)).flatMapF(multiply(_, 3)).run发布于 2016-02-23 20:22:38
您可以考虑使用scalaz.concurrent.Task
def init(a: Int): Task[Int] = Task.now(a)
def add(a: Int, b: Int): Task[Int] = Task.now(a + b)
def multiply(a: Int, b: Int): Task[Int] = Task.now(a * b)所以:
scala> val res = init(3).flatMap(add(_, 4)).flatMap(multiply(_, 3))
res: scalaz.concurrent.Task[Int] = scalaz.concurrent.Task@3fdb3076可以很容易地转换为:
scala> res.get
res1: scalaz.concurrent.Future[scalaz.\/[Throwable,Int]] = ...
scala> res.get.run
res5: scalaz.\/[Throwable,Int] = \/-(21)如果您需要失败:
scala> def add(a: Int, b: Int): Task[Int] = Task.fail(new RuntimeException("fail"))
add: (a: Int, b: Int)scalaz.concurrent.Task[Int]
scala> init(3).flatMap(add(_, 4)).flatMap(multiply(_, 3)).get.run
res4: scalaz.\/[Throwable,Int] = -\/(java.lang.RuntimeException: fail)请注意,这里的Future是scalaz.concurrent.Future
更新
如果您需要将Either传递给任务-您可以使用以下命令:
import Task._
implicit class FutureToTask[T](f: Future[\/[Throwable, T]]){
def task = async(f.runAsync)
}https://stackoverflow.com/questions/35576257
复制相似问题