在下面的递归recHelper
方法中,如果所有元素都返回Right
,则需要返回Futures列表,否则为Left
。问题是我无法连接结果。如何使这个代码工作?
def either1 (i:Int): Future[Either[String,Int]] = Future {
if (i<3)
Right(i*2)
else
Left("error 1")
}
def either2 (i:Int): Future[Either[String,Int]] = Future {
if (i<3)
Right(i*2)
else
Left("error 2")
}
val seq = Seq (1,1,2,2)
def recHelper(remaining: List[Int]): Future[Either[String, Seq[Int]]] = {
remaining match {
case Nil => Nil
case h :: t => (if (h % 2 == 0) either1(h) else either2(h)).map {
headEither =>
headEither match {
case Left(s) => Future { Left(s) }
case Right(n) => Future { n :: recHelper(t) :: Nil } /// ERROR
}
}
}
}
recHelper(seq.toList)
答案 0 :(得分:2)
Nil => Nil
案例表明您应该再次阅读Future
以及Either
monad所做的事情:Nil
被推断为{{1}类型}。它缺少monadic List[Int]
的两个应用程序,即:
unit
以使其Right
Either[List[Int]]
,以使其Future
同样适用于其他情况。这是一个有效的版本:
Future[Either[List[Int]]
您不能意外地使用两个堆叠的monad构建复杂的嵌套for-comprehension。我再强烈建议你去看看Scala Cats和import scala.concurrent._
import scala.util._
import scala.concurrent.ExecutionContext.Implicits.global
def either1(i: Int): Future[Either[String, Int]] = Future {
if (i<3) Right(i*2)
else Left("error 1")
}
def either2(i: Int): Future[Either[String, Int]] = Future {
if (i<3) Right(i*2)
else Left("error 2")
}
val seq = Seq(1, 1, 2, 2)
def recHelper(remaining: List[Int]): Future[Either[String, List[Int]]] = {
remaining match {
case Nil => Future { Right(Nil) }
case h :: t => for {
hEith <- (if (h % 2 == 0) either1(h) else either2(h))
res <- (hEith match {
case Left(s) => Future { Left(s) }
case Right(n) => for {
tEith <- recHelper(t)
} yield tEith.map(n :: _)
})
} yield res
}
}
recHelper(seq.toList)
。他们构建monad变换器库并不是(仅)为了好玩:同时处理两个堆叠的monad实际上非常痛苦。
答案 1 :(得分:2)
另一种解决方案:
def recHelper(remaining :Seq[Int]
,acc :Seq[Int] = Seq()
) :Future[Either[String, Seq[Int]]] = remaining match {
case Seq() => Future(Right(acc))
case h +: t => (if (h % 2 == 0) either1(h) else either2(h)).flatMap {
case Left(s) => Future(Left(s))
case Right(n) => recHelper(t, n +: acc)
}
}
recHelper(seq)
//res0: Future[Either[String,Seq[Int]]] = Future(Right(List(4, 4, 2, 2)))