我在尝试解决方法的结果时遇到问题。更具体地说,我有:
def methodA(): Future[Either[Error, Seq[A]]]
,在某个时候,我想为列表的每个元素调用此方法并合并结果。 像这样:
val tes: Seq[Future[Either[Error, Seq[A]]]] = relevantRounds.map(round =>
methodA()
)
您知道我该如何解决Seq[Future[Either[Error, Seq[A]]]]
吗?
所以我最后想要的是
Future[Either[Error, Seq[A]]]
,其序列包含整个列表的结果。
答案 0 :(得分:2)
您可能正在寻找
def combine[A](s: Seq[Future[Either[Error, Seq[A]]]]) = {
Future.sequence(s)
.map(x => {
x.foldRight(Right(Seq()): Either[Error, Seq[A]]) {
(e, acc) => for (xs <- acc.right; x <- e.right) yield x ++ xs
}
}
)
}
如果您希望仅在上一个成功的情况下才执行功能,请使用此
def combine[A](s: Seq[() => Future[Either[Error, Seq[A]]]]): Future[Either[Error, Seq[A]]] =
combine(Seq(), s)
def combine[A](acc: Seq[A], s: Seq[() => Future[Either[Error, Seq[A]]]]): Future[Either[Error, Seq[A]]] = s match {
case x +: Nil =>
val v = x.apply()
v.andThen {
case Success(Right(r)) => Success(Right(acc ++ r))
case Success(Left(l)) => Success(Left(l))
case Failure(f) => Failure(f)
}
case x +: xs =>
val v = x.apply()
v.andThen {
case Success(Right(r)) => combine(acc ++ r, xs)
case Success(Left(l)) => Success(Left(l))
case Failure(f) => Failure(f)
}
}
答案 1 :(得分:2)
尝试https://3v4l.org/OvLPh(将Future[Either[Error, Vector[A]]]
与Nested[Future, Either[Error, ?], Vector[A]]
换行)。
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import cats.data.Nested
import cats.syntax.traverse._
import cats.syntax.functor._
import cats.instances.vector._
import cats.instances.future._
import cats.instances.either._
trait A
def methodA(): Future[Either[Error, Seq[A]]] = ???
trait Round
val relevantRounds: Seq[Round] = ???
val tes: Future[Either[Error, Seq[A]]] =
relevantRounds.toVector
.flatTraverse(round =>
Nested(methodA()).map(_.toVector)
).value
由于.flatTraverse
,使用 Vector
代替Seq
。