简体   繁体   English

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

[英]How to get Future[\/[Throwable, T]] from several Future[\/[Throwable, T]]

Assuming I have several methods to return \\/[Throwable, String] . 假设我有几种方法可以返回\\/[Throwable, String] The right value Int is what I want and the left value accumulates errors. 正确的值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

It looks good, because scalaz either's flatmap is right biased, so it will operate based on the right value. 它看起来不错,因为scalaz要么平面图是正确的偏差,所以它将基于正确的值运行。

However, if method is going to change for the API call, so the return type would be Future[ErrorOr[T]] . 但是,如果要为API调用更改方法,则返回类型将为Future[ErrorOr[T]] Is there any way I can use to return Future[ErrorOr[T]] ? 有什么方法可以用来返回Future[ErrorOr[T]]吗? Also, I probably want to use future.flatMap as a callback instead of using await here to block 另外,我可能想使用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)

您可以将init的结果包装在EitherT monad转换器中,使用flatMapF而不是flatMap来直接使用addmultiply ,就像现在一样,然后调用run来获取Future[ErrorOr[Int]]

EitherT(init(3)).flatMapF(add(_, 4)).flatMapF(multiply(_, 3)).run

You might consider using scalaz.concurrent.Task : 您可以考虑使用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)

So: 所以:

scala> val res = init(3).flatMap(add(_, 4)).flatMap(multiply(_, 3))
res: scalaz.concurrent.Task[Int] = scalaz.concurrent.Task@3fdb3076

Can be easily converted to: 可以很容易地转换为:

scala> res.get
res1: scalaz.concurrent.Future[scalaz.\/[Throwable,Int]] = ...

scala> res.get.run
res5: scalaz.\/[Throwable,Int] = \/-(21)

If you need to fail: 如果您需要失败:

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)

Please note, that the Future here is scalaz.concurrent.Future 请注意,这里的Futurescalaz.concurrent.Future

Update 更新

If you need to pass Either to the Task - you can use this: 如果您需要将Either传递给任务 - 您可以使用:

import Task._

implicit class FutureToTask[T](f: Future[\/[Throwable, T]]){
   def task = async(f.runAsync)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将 Future[Either[Throwable,T]] 展开为 Either[Throwable,T] - How to unwrap a Future[Either[Throwable,T ]] to Either[Throwable,T] 未来[A]与未来[Throwable \\ / A] - Future[A] vs Future[Throwable \/ A] 是否可以将输出为Either [Throwable,Unit]的同步函数调用转换为Future [Either [Throwable,Unit]]? - Is it possible to convert synchronous function call with output of Either[Throwable, Unit] to Future[Either[Throwable, Unit]]? scalatra case t:Throwable => t.printStacktrace() - scalatra case t: Throwable => t.printStacktrace() 如何在Throwable Scala对象中获取数据? - How to get data inside a Throwable Scala object? 如何将Throwable \\ / List [Throwable \\ / A]序列化为scalaz中的Throwable \\ / List [A]? - How to sequence Throwable \/ List[Throwable \/ A] into Throwable \/ List[A] in scalaz? Scala从Future [Seq [T]]提取值到Future [T] - Scala extract value from Future[Seq[T]] into Future[T] ZIO 在 Future[Either[MyException, A]] 中传播自定义异常系列,没有仅可抛出的任务 - ZIO Propagate custom exception family within Future[Either[MyException, A]], without Task which is Throwable only 获取Future [List [Future [T]]]但需要Future [List [T]](浓缩模式) - Get a Future[List[Future[T]]] but need Future[List[T]] (enrichment patttern) Scala Option[Future[T]] 到 Future[Option[T]] - Scala Option[Future[T]] to Future[Option[T]]
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM