scala - 嵌套表达式

标签 scala

是否有更简洁的方法,即没有嵌套的 for 表达式,来编写以下 fgdoIt 函数?

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

def f(x: Int): Future[Either[String, Int]] = Future(Right(100))

def g(x: Either[String, Int], y: Int): Future[Either[String, Int]] = 
   Future { x match {
    case Right(i)  => Right(i + y)
    case Left(err) => Left(err)
}}

def doIt: Future[Either[String, Int]] = for {
    x <- for { a <- f(100) } yield a
    y <- for { a <- g(x, 25) } yield a
} yield y

我推测我可以使用 Monad Transformers,但我不理解它们。

最佳答案

如果你正在使用像 Foo[Qux[A]] 这样的类型,其中 FooQux 都是单子(monad),你会发现你正在编写大量嵌套的for-comprehensions,你应该做的第一件事是检查Scalaz(或cats)是否有QuxT monad transformer。这将允许您使用 QuxT[Foo, A] 值与单个级别的 for monadically 一起工作。

正如其他答案所指出的,根据您对 g 的定义,您实际上并不需要嵌套的 for - 理解。我假设您想在 Future[Either[String, ?]] 中一直使用值,而没有嘈杂的 g 方法,其中如果你想要一个 EitherT[Future, String, Int]:

import scalaz._, Scalaz._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

def f(x: Int): EitherT[Future, String, Int] =
  EitherT.fromEither(Future[Either[String, Int]](Right(100)))

// Or just:
// def f(x: Int): EitherT[Future, String, Int] = EitherT.right(Future(100))

def doIt: EitherT[Future, String, Int] = f(100).map(_ + 25)

最终你会编写 doIt.run 来获得 Future[Either[String, Int]]:

scala> doIt.run.onSuccess { case e => println(e) }
\/-(125)

这与您的实现给出的结果相同(除了我们有 Scalaz 的析取类型)。

关于scala - 嵌套表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31325358/

相关文章:

scala - 将 Akka 流连接到 JMS

scala - 如何正确使用 MonadError?

java - 使用 MapMaker#makeComputingMap 防止同一数据同时发生 RPC

java - 是否可以用 selenium 模拟键盘行为?

scala - Scala 的匹配是否是表达式?

scala - 使用默认值初始化时未绑定(bind)的占位符参数

scala - 如何将参数传递给惰性值

scala - 使用 slf4j-simple 进行流畅的日志记录

Java加密,重置IV可以提高性能吗?

java - 为什么我似乎不能从 build.sbt 中排除这种传递依赖? (继续出现在ivyReport)