【问题标题】:Scala 2.12 combination of Future and Either (biased version)Scala 2.12 Future 和 Either 的组合(有偏见的版本)
【发布时间】:2018-01-02 19:30:24
【问题描述】:

我有两个方法,并且都返回 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)

但现在我想使用以下语法捕获错误,并传播到最终结果。实现这一目标的最佳方法是什么?也应该使用 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]] = ???

我知道使用猫转换单子可以简化这一点。欢迎给我使用标准库和猫的解决方案。

【问题讨论】:

  • 如果您只是使用EitherLeft 返回一个String,我认为这是一条包含错误的文本消息,为什么不简单地使用SuccessFailure 内置进入Future?
  • 猜你可能想看看EitherT from cats or scalaz
  • @Yaneeve 我只是想让它变得简单,它实际上是一个自定义的错误对象。
  • @TomerSela 是的,我看到了这篇文章,这个例子并没有真正链接两个期货,它更多的是关于并行执行,这很简单。另外我的问题更多的是关于设计,我们应该只传递值还是传递一个?谢谢。

标签: scala


【解决方案1】:

正如 cmets 所提到的,这是 cat 和 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
  }
}

使用适当的类型实现 mapflatMap 可以实现完全相同的理解风格:

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)

【讨论】:

  • 问题是我们如何将FutureEither[C] 转换回Future[Either[String, C]]?谢谢。
  • 随便.wrapped
猜你喜欢
  • 2016-01-23
  • 1970-01-01
  • 2015-01-05
  • 1970-01-01
  • 2015-10-18
  • 2015-12-28
  • 2013-05-19
  • 2021-01-18
  • 2020-09-18
相关资源
最近更新 更多