首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >左flatMap on EitherT

左flatMap on EitherT
EN

Stack Overflow用户
提问于 2017-01-15 14:35:47
回答 1查看 1.7K关注 0票数 3

假设我有返回Future[Either[_, _]的函数,我希望在发生故障时应用其中一些函数,这意味着只将它们应用到左侧。简化的例子是:

代码语言:javascript
复制
def operation1: Future[Either[String, Int]] = Future.successful(Right(5))
def operation2: Future[Either[String, Int]] = Future.successful(Left("error"))
def operation2FallBackWork = Future.successful{
  println("Doing some revert stuff")
  Left("Error happened, but reverting was successful")
}

val res = for {
  res1 <- EitherT.fromEither(operation1)
  res2 <- EitherT.fromEither(operation2)//.leftFlatMap(operation2FallBackWork) -????
} yield res1 + res2

Await.result(res.toEither, 5 seconds)

如何做到这一点?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-01-15 17:12:42

leftFlatMap最接近的是MonadErrorhandleError,它具有您希望从leftFlatMap中获得的签名(但请注意,您需要将回退操作更改为EitherT,并提供一个常量函数,而不是按原样传递)。

代码语言:javascript
复制
import scala.concurrent.{ Await, Future }
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scalaz._, Scalaz._

def operation1: Future[Either[String, Int]] = Future.successful(Right(5))
def operation2: Future[Either[String, Int]] = Future.successful(Left("error"))

def operation2FallBack: EitherT[Future, String, Int] = EitherT(
  Future.successful {
    println("Doing some revert stuff")
    "Error happened, but reverting was successful".left
  }
)

val E: MonadError[({ type L[x] = EitherT[Future, String, x] })#L, String] =
  implicitly

val res = for {
  a <- EitherT.fromEither(operation1)
  b <- E.handleError(EitherT.fromEither(operation2))(_ => operation2FallBack)
} yield a + b

Await.result(res.toEither, 5.seconds)

您还可以使用MonadError提供的语法,使其看起来像是EitherT有一个handleError方法,尽管要让Scala编译器认识到您的操作具有正确的形状需要更多的步骤:

代码语言:javascript
复制
import scala.concurrent.{ Await, Future }
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scalaz._, Scalaz._

type FE[x] = EitherT[Future, String, x]

def operation1: FE[Int] = EitherT(Future.successful(5.right))
def operation2: FE[Int] = EitherT(Future.successful("error".left))

def operation2FallBack: FE[Int] = EitherT(
  Future.successful {
    println("Doing some revert stuff")
    "Error happened, but reverting was successful".left
  }
)

val res = for {
  a <- operation1
  b <- operation2.handleError(_ => operation2FallBack)
} yield a + b

Await.result(res.toEither, 5.seconds)

我更喜欢这第二个版本,但这是一个风格和品味的问题。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41662300

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档