假设我有几种方法可以返回\/[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)
答案 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
来使用flatMap
和add
与您现在直接相同,然后致电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)
}