如何在Scala中重构嵌套的Option.folds?

时间:2015-04-10 18:33:23

标签: scala refactoring

假设我正在使用给定的foo:Int => Statusf1: Int => Option[Int]撰写f2: Int => Option[Int],如下所示:

def f1(x: Int): Option[Int] = ???
def f2(y: Int): Option[Int] = ???

sealed trait Status
object Error1 extends Status
object Error2 extends Status
case class Ok(x:Int) extends Status

// probably not necessary
def error1: Status = Error1
def error2: Status = Error2
def ok(z: Int): Status = Ok(z)

def foo(x: Int): Status = f1(x).fold(error1){y => f2(y).fold(error2){z => ok(z)}}

IMO嵌套folds看起来很笨拙。你会如何重构它?

1 个答案:

答案 0 :(得分:4)

如果您使用Either,则可以执行以下操作。它看起来更好,如果它可以理解取决于你是如何放心。

val either = for {
  y <- f1(x).toRight(error1).right
  z <- f2(y).toRight(error2).right
} yield ok(z)

either.merge

一些背景知识:

如果定义了选项,则

Option.toRight转换为Right(成功案例),否则返回参数的Left(错误情况)。

Either.rightEither投射到右侧,即monadic操作使RightSomeLeftNone,但如果我们在左边的情况下,它会保留Left值。

Either.merge仅适用于Either[A, A]并返回LeftRight中的任何值。