解决Seq [Future [Either [A,Seq [B]]]]-Scala猫

时间:2019-05-06 07:45:10

标签: scala future scala-cats cats-effect

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

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

2 个答案:

答案 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