如何在 Scala 中重构嵌套的 Option.folds?
How to refactor nested Option.folds in Scala?
假设我用给定的 f1: Int => Option[Int]
和 f2: Int => Option[Int]
编写 foo:Int => Status
如下:
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
看起来很笨拙。你会如何重构它?
如果您喜欢使用 Either
,您可以执行以下操作。比较好看,能不能看得懂就看你对哪一个都放心了。
val either = for {
y <- f1(x).toRight(error1).right
z <- f2(y).toRight(error2).right
} yield ok(z)
either.merge
一些背景:
如果定义了选项,Option.toRight
转换为 Right
(成功案例),否则 returns 参数的 Left
(错误案例)。
Either.right
将 Either
投射到右边,即单子操作使得 Right
是 Some
,Left
是 None
, 但如果我们在左边的情况下,它会保留 Left
值。
Either.merge
仅适用于 Either[A, A]
和 returns Left
或 Right
.
中的任何值
假设我用给定的 f1: Int => Option[Int]
和 f2: Int => Option[Int]
编写 foo:Int => Status
如下:
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
看起来很笨拙。你会如何重构它?
如果您喜欢使用 Either
,您可以执行以下操作。比较好看,能不能看得懂就看你对哪一个都放心了。
val either = for {
y <- f1(x).toRight(error1).right
z <- f2(y).toRight(error2).right
} yield ok(z)
either.merge
一些背景:
如果定义了选项,Option.toRight
转换为 Right
(成功案例),否则 returns 参数的 Left
(错误案例)。
Either.right
将 Either
投射到右边,即单子操作使得 Right
是 Some
,Left
是 None
, 但如果我们在左边的情况下,它会保留 Left
值。
Either.merge
仅适用于 Either[A, A]
和 returns Left
或 Right
.