我有两个方法,两个都返回Future [Either [String,T]],并希望将它们链接在一起以完成工作。我正在使用Scala 2.12现在两者都是正确的偏见。
例如,
如果函数没有返回Future和Either组合,我可以简单地执行以下操作以获得理解。
def convert(a, b) = ???
def callA(): Future[A] = ???
def callB(a: A): Future[B] = ???
def chain: Future[C] = for {
a <- callA
b <- callB(a)
} yield convert(a, b)
但现在我想使用以下语法使用Either捕获错误,并传播到最终结果。实现这一目标的最佳方法是什么?还应该使用callB还是callB1?
def convert(a, b): Future[Either[String, C]] = ???
def callA(): Future[Either[String, A]] = ???
def callB(a: A): Future[Either[String, B]] = ??? or
def callB1(eithera: Either[String, A]): Future[Either[String, B]] = ???
我知道使用cat变换monad可以简化这一点。欢迎给我使用标准库和猫的解决方案。
答案 0 :(得分:6)
正如评论所提到的,这是猫和scalaz可以处理的事情。但我也能理解不要为一小段逻辑引入另一个依赖或复杂的愿望。如果你想自己实现它,你可以做什么:
implicit class FutureEither[A](val wrapped: Future[Either[String, A]])(implicit ec: ExecutionContext) {
def map[B](f: A => B): FutureEither[B] = wrapped.map(_.map(f))
def flatMap[B](f: A => FutureEither[B]): FutureEither[B] = wrapped.flatMap {
case Left(s) => Future(Left(s))
case Right(a) => f(a).wrapped
}
}
使用适当的类型实现map
和flatMap
可以实现完全相同的理解:
def convert(a: A, b: B): C = ???
def callA(): FutureEither[A] = ???
def callB(a: A): FutureEither[B] = ???
def chain: FutureEither[C] = for {
a <- callA()
b <- callB(a)
} yield convert(a, b)