使用返回Future的二元操作对序列进行折叠

5
假设我有一个函数 op: (Int, Int) => Future[Int],需要编写一个新函数 foo
def foo(xs: Seq[Int], 
        zero: Int, 
        op: (Int, Int) => Future[Int]): Future[Int] = ???

foo 应该像 foldLeft 一样对 xs 中的所有元素按顺序应用 op,例如:

val op: (Int, Int) => Future[Int] = (x, y) => Future(x + y)
val xs = (1 to 10)
val fut = foo(xs, 0, op) // should return Future of 55
fut.value // Some(Success(55))

你如何实现foo

3个回答

6

我不确定为什么其他答案被删除了 - 但是在使用 纯Scala 的情况下,这对我有效:

 def foo(xs: Seq[Int], zero: Int, op: (Int, Int) => Future[Int]): Future[Int] =  

    xs.foldLeft(Future.successful(zero))((a, b) => a.flatMap(op(_, b)))

我有遗漏吗?


5
尝试使用来自cats的foldM
import cats._
import cats.implicits._

def foo(xs: Seq[Int], zero: Int, op: (Int, Int) => Future[Int]): Future[Int] =
  Foldable[List].foldM(xs.toList, zero)(op)

谢谢。这是一个很好的例子,说明为什么cats很有用,但我现在更喜欢一个纯Scala的解决方案。 - Michael

2

不使用外部库:

实现一个“特殊”的foldLeft

Original Answer翻译成"最初的回答"

def foldLeft[Int](xs: Seq[Int], z: Int)(op: (Int, Int) => Future[Int]): Future[Int] = {
 def f(xs: Seq[Int], accF: Future[Int]): Future[Int] = xs match {
   case Seq()   => accF
   case x +: xs => accF.flatMap(acc => f(xs, op(acc, x)))
 }

 f(xs, Future.successful(z))

最初的回答:

并使用它:

def foo(xs: Seq[Int], 
    zero: Int, 
    op: (Int, Int) => Future[Int]): Future[Int] = foldLeft(xs, zero)(op)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接