3

我在堆栈中了解 Scala 的for工作原理。我认为下面的代码可以用for虽然我不知道怎么写。有人可以解释一下我该怎么做吗?

def foo: Future[Option[Int]] = ???
def bar: Future[Throwable Xor Option[Int]] = ???
def baz: Future[Option[Boolean]] = ???

foo.flatMap {
  case Some(x) =>
    Future.successful(x)
  case None =>
    bar.flatMap {
      case Xor.Right(Some(x)) =>
        baz.map {
          case true => 1
          case false => 0
        }
      case Xor.Right(None) =>
        Future.successful(0)
      case Xor.Left(_) =>
        Future.successful(-1)
    }
}
4

2 回答 2

4

有了flatMap函数内部的所有分支,就不可能把它写成理解。

可以用fold方法替换模式匹配,但这可能是个人喜好问题。

Option("suish") match {
  case Some(name) => s"hello $name"
  case None => "hello world"
}
// is analogous to
Option("suish").fold("hello world")(name => s"hello $name")

我使用( tutorial )和的fold方法重写了您的模式匹配,但我不确定这是否比您的嵌套模式匹配更具可读性。OptionTXorTOption

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import cats.implicits._
import cats.data.{Xor, XorT, OptionT}

def foo: Future[Option[Int]] = none[Int].pure[Future]
def bar: Future[Throwable Xor Option[Int]] = 2.some.right.pure[Future]
def baz: Future[Option[Boolean]] = true.some.pure[Future]

OptionT(foo).getOrElseF {
  // foo : case None
  XorT(bar).fold(
    // bar : case Xor.Left
    _ => -1.pure[Future],
    barO => barO.fold(
      // bar : case Xor.Right(None)
      0.pure[Future])(
      // bar : case Xor.Right(Some(x))
      _ => baz.map(_.fold(0 /* ? */)(b => if (b) 1 else 0)))
  ).flatten
}
// Future[Int]
于 2016-05-26T13:00:41.463 回答
3

无法在 for-comprehensions 中进行模式匹配。请参阅Allow pattern matching on type in for comprehensions

也许你可以使用Monad Transformers。我确实想以这种方式实现您的代码,但我现在没有时间。也许提示可以帮助你。

/Edit 正如谢尔盖的评论所指出的那样,这并不完全正确。只要所有匹配的类型相同,您就可以在 for-comprehensions 中进行模式匹配。这张图片取自Scala Coursera Course 函数式程序设计第一周的第二课,其中所有模式都继承自JSON

理解和模式匹配

于 2016-05-26T10:20:04.547 回答