3

我在尝试解决方法的结果时遇到问题。更具体地说,我有:

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]]]一个包含整个列表结果的序列。

4

2 回答 2

2

尝试(用.flatTraverse包裹)。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

Vector被使用而不是Seq因为原因

于 2019-05-06T09:10:10.700 回答
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)
      }
  }
于 2019-05-06T08:15:13.887 回答