假设我正在使用给定的foo:Int => Status
和f1: 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
看起来很笨拙。你会如何重构它?
答案 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.right
将Either
投射到右侧,即monadic操作使Right
为Some
,Left
为None
,但如果我们在左边的情况下,它会保留Left
值。
Either.merge
仅适用于Either[A, A]
并返回Left
或Right
中的任何值。