嵌套表达式 [英] Nested For Expressions

查看:57
本文介绍了嵌套表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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]] 这样的类型,其中 FooQux 是单子,你发现你写了很多嵌套的 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 fors.

正如其他答案所指出的,鉴于您对 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆