对Scala Future[或]的优雅处理
我有一种形状如下的类型:对Scala Future[或]的优雅处理,scala,either,Scala,Either,我有一种形状如下的类型: val myType: Future[Either[MyError, TypeA]] = // some value case class MyException(e: MyError) extends Exception def eitherToException[A](f: Future[Either[MyError,A]]): Future[A] = { f.flatMap { case Left(e) => Future.failed(My
val myType: Future[Either[MyError, TypeA]] = // some value
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)
我知道我可以在此基础上进行模式匹配,并得到右边或左边的类型,但问题是我必须嵌套我的模式匹配逻辑。我在寻找更优雅的处理方式?有什么建议吗?如果您将
MyError
编码为例外,您也不再需要了,可以简单地对完成进行模式匹配,或者使用recoverWith
将其映射到另一种类型:
myType.onComplete {
case Success(t) =>
case Failure(e) =>
}
要映射现有的类型,可以执行以下操作:
val myType: Future[Either[MyError, TypeA]] = // some value
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)
或者,如果MyError
和TypeA
在您的控制下,您可以创建一个通用的超级类型和模式匹配:
sealed trait MyResult
final case class MyError() extends MyResult
final case class TypeA() extends MyResult
myType.map {
case MyError() => ...
case TypeA() => ...
}
如果将MyError
编码为例外,则不再需要或,只需根据完成情况进行模式匹配,或使用recoverWith
将其映射到其他类型:
myType.onComplete {
case Success(t) =>
case Failure(e) =>
}
要映射现有的类型,可以执行以下操作:
val myType: Future[Either[MyError, TypeA]] = // some value
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)
或者,如果MyError
和TypeA
在您的控制下,您可以创建一个通用的超级类型和模式匹配:
sealed trait MyResult
final case class MyError() extends MyResult
final case class TypeA() extends MyResult
myType.map {
case MyError() => ...
case TypeA() => ...
}
您可以创建自定义提取器对象:
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
}
}
及
您可以创建自定义提取器对象:
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
}
}
及
不将MyResult作为超级类型是行不通的,我觉得为了它而利用继承不是一个好主意!TypeA只是一个例子,因为我的所有服务方法都返回一个带有MyError或服务方法正在处理的相应case类类型的!我认为最优雅的解决方案是涉及myFuture.onComplete并使MyError成为例外的解决方案。这很有道理,很有效,很优雅。撇开评论不谈,@sparkr检查你的举止,朋友。@Arne:谢谢你的帖子,但我对以蛋糕模式的名义使用无意义的继承结构感到非常恼火,因为继承类和继承类根本没有关系!对不起,如果我不礼貌的话@斯巴克:没问题。密封的特征编码case类是消息传递的常见模式,例如Akka。与OO语言相比,它确实闻起来像是继承错误的使用,但作为一种scala模式(我最近做了很多Akka,所以我的思维在一个消息框架中)是被广泛接受的。不!将MyResult作为超级类型是行不通的,我觉得为了它而利用继承不是一个好主意!TypeA只是一个例子,因为我的所有服务方法都返回一个带有MyError或服务方法正在处理的相应case类类型的!我认为最优雅的解决方案是涉及myFuture.onComplete并使MyError成为例外的解决方案。这很有道理,很有效,很优雅。撇开评论不谈,@sparkr检查你的举止,朋友。@Arne:谢谢你的帖子,但我对以蛋糕模式的名义使用无意义的继承结构感到非常恼火,因为继承类和继承类根本没有关系!对不起,如果我不礼貌的话@斯巴克:没问题。密封的特征编码case类是消息传递的常见模式,例如Akka。与OO语言相比,它闻起来确实像是继承错误使用,但作为一种scala模式(我最近做了很多Akka,所以我的思维在一个消息框架中)它听起来像是需要monad transformers,不幸的是scala核心没有提供。scalaz中可比较的类型是EitherT[Task,MyError,TypeA]
。你可以用一种合理的方式在上面做一些操作,比如map
,flatMap
,等等。不!使用scalaz不是此项目的选项!不能添加依赖项?我想你可以自己玩游戏吗?我终于做到了!我自己想出了一个更进一步的实现!听起来你需要monad变压器,不幸的是scala内核没有提供。scalaz中可比较的类型是EitherT[Task,MyError,TypeA]
。你可以用一种合理的方式在上面做一些操作,比如map
,flatMap
,等等。不!使用scalaz不是此项目的选项!不能添加依赖项?我想你可以自己玩游戏吗?我终于做到了!我自己想出了一个更进一步的实现!