是否有更简洁的方法,即没有嵌套的 for 表达式
,来编写以下 f
、g
和 doIt
函数?
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]]
这样的类型,其中 Foo
和 Qux
都是单子(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/