当前位置:  开发笔记 > 编程语言 > 正文

在EitherT上留下flatMap

如何解决《在EitherT上留下flatMap》经验,为你挑选了1个好方法。

假设我有返回的函数,Future[Either[_, _]我想在失败的情况下应用其中的一些函数,这意味着只将它们应用于左侧.简化的例子是:

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)

怎么实现呢?



1> Travis Brown..:

最接近a的leftFlatMapMonadError's handleError,它具有你期望从被调用的东西中获得的签名leftFlatMap(尽管请注意,你需要将后备操作更改EitherT为a并提供常量函数,而不是按原样传递它).您可以EitherT像这样直接使用实例:

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编译器识别您的操作具有正确的形状:

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)

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

推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有