如何从几个未来[\ / [Throwable,T]]获得未来[\ / [Throwable,T]]

时间:2016-02-23 11:24:18

标签: scala scalaz

假设我有几种方法可以返回\/[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)

2 个答案:

答案 0 :(得分:3)

您可以将$books_price = array(); while($pp_info = mysqli_fetch_array($sqlpinfo)){ $product_title = $pp_info['book_name']; $books_image = $pp_info['book_upload']; $books_price[] = $pp_info['book_price']; } $sum = array_sum($books_price); // For debug var_dump($books_price) echo $sum; 的结果包装在init monad变换器中,使用EitherT代替flatMapF来使用flatMapadd与您现在直接相同,然后致电multiply以获取run

Future[ErrorOr[Int]]

答案 1 :(得分:3)

您可以考虑使用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)
}