【问题标题】:Elegant Handling of Scala Future[Either]]Scala Future 的优雅处理[Either]]
【发布时间】:2016-01-23 10:09:05
【问题描述】:

我有一个形状像这样的类型:

val myType: Future[Either[MyError, TypeA]] = // some value

我知道我可以对此进行模式匹配并获得 Right 或 Left 类型,但问题是我必须嵌套我的模式匹配逻辑。我正在寻找更优雅的处理方式?有什么建议吗?

【问题讨论】:

  • 听起来你需要monad转换器,不幸的是scala核心不提供。 scalaz 中的可比类型是EitherT[Task, MyError, TypeA]。您可以通过合理的方式进行mapflatMap 等操作。
  • 不!使用 scalaz 不是这个项目的选项!
  • 不能添加依赖?我想你可以推出自己的EitherT
  • 我最终做到了!我自己想出了一个 EitherFut 实现!

标签: scala either


【解决方案1】:

如果您将 MyError 编码为异常,则不再需要 Either 并且可以简单地对完成进行模式匹配,或者使用 recoverWith 将其映射到另一种类型:

myType.onComplete {
  case Success(t) =>
  case Failure(e) =>
}

要映射您现有的 Either 类型,您可以执行以下操作:

case class MyException(e: MyError) extends Exception

def eitherToException[A](f: Future[Either[MyError,A]]): Future[A] = {
  f.flatMap {
    case Left(e) => Future.failed(MyException(e))
    case Right(x) => Future.successful(x)
  }
}

val myType2 = eitherToException(myType)

或者,如果 MyErrorTypeA 在您的控制之下,您可以创建一个通用的超类型和模式匹配:

sealed trait MyResult
final case class MyError() extends MyResult
final case class TypeA() extends MyResult

myType.map {
  case MyError() => ...
  case TypeA() => ...
}

【讨论】:

  • 不!将 MyResult 作为超类型是行不通的,我认为利用继承并不是一个好主意! TypeA 只是一个例子。因为我的所有服务方法都返回带有 MyError 的 Either 或服务方法正在处理的相应案例类类型!
  • 我认为最优雅的解决方案是涉及 myFuture.onComplete 并使 MyError 异常。这是有道理的,它有效,它很优雅。除了评论,@sparkr 检查你的礼貌朋友。
  • @Arne:感谢您的帖子,但我一直对以 Cake 模式的名义使用无意义的继承结构感到非常恼火,其中继承类和被继承类根本没有关系!对不起,如果我不礼貌!
  • @sparkr 没问题。密封特征编码案例类是消息传递的常见模式,例如 Akka。与 OO 语言相比,它确实闻起来像滥用继承,但作为一种 scala 模式被广泛接受(而且我最近一直在做很多 Akka,所以我的想法是在一个消息框架中)
【解决方案2】:

您可以创建自定义提取器对象:

object FullSuccess {
  def unapply[T](x: Try[Either[MyError, T]]) = x match {
    case Success(Right(x)) => Some(x)
    case _ => None
  }
}

object PartSuccess {
  def unapply[T](x: Try[Either[MyError, T]]) = x match {
    case Success(Left(err)) => Some(err)
    case _ => None
  }
}

还有

val myType: Future[Either[MyError, TypeA]] = // some value

myType.onComplete {
  case FullSuccess(x) => ... // equivalent to case Success(Right(x))
  case PartSuccess(x) => ... // equivalent to case Success(Left(x))
  case Failure(e) => ...
}

【讨论】:

    猜你喜欢
    • 2015-12-28
    • 2015-01-05
    • 1970-01-01
    • 2015-01-26
    • 2021-01-18
    • 1970-01-01
    • 2019-04-29
    • 2019-09-23
    • 1970-01-01
    相关资源
    最近更新 更多