嵌套表达式 [英] Nested For Expressions
问题描述
有没有更简洁的方法,即没有嵌套的for表达式
,来编写下面的f
、g
和doIt
函数?
Is there a cleaner way, i.e. without the nested for expressions
, to write the following f
, g
, and doIt
functions?
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,但我不理解它们.
I'm speculating that I could use Monad Transformers, but I don't understand them.
推荐答案
如果您正在使用像 Foo[Qux[A]]
这样的类型,其中 Foo
和Qux
是单子,你发现你写了很多嵌套的 for
-comprehensions,你应该做的第一件事是检查 Scalaz(或 cats) 用于 QuxT
monad 转换器.这将允许您使用 for
的单个级别来处理 QuxT[Foo, A]
值.
If you're working with types like Foo[Qux[A]]
where both Foo
and Qux
are monads and you find that you're writing a lot of nested for
-comprehensions, the first thing you should do is check Scalaz (or cats) for a QuxT
monad transformer. That will allow you to work with QuxT[Foo, A]
values monadically with a single level of for
s.
正如其他答案所指出的,鉴于您对 g
的定义,您实际上并不需要嵌套的 for
-comprehensions.我将假设您希望在 Future[Either[String, ?]]
中一直使用值,而没有嘈杂的 g
方法,其中如果你想要一个 EitherT[Future, String, Int]
:
As the other answers point out, you don't actually need the nested for
-comprehensions in your case given your definition of g
. I'm going to assume that you want to work with values all the way inside the Future[Either[String, ?]]
, without the noisy g
method, in which case you want an 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]]
:
Eventually you'd write doIt.run
to get a Future[Either[String, Int]]
:
scala> doIt.run.onSuccess { case e => println(e) }
\/-(125)
这与您的实现给出的结果相同(除了我们有 Scalaz 的析取类型).
Which is the same result your implementation gives (except that we've got Scalaz's disjunction type).
这篇关于嵌套表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!