我有一些代码如下所示:
data class MyStrings(val a: String, val b: String)
sealed class Error {
object SpecificError0 : Error()
object SpecificError1 : Error()
object SpecificError2 : Error()
}
fun either2(): Either<Error, String> =
Either.catch { throw RuntimeException("Either 2") }.mapLeft { Error.SpecificError2 }
fun either4(): Either<Error, MyStrings> =
Either.catch {
MyStrings(
a = "Hello",
b = either2().getOrElse { "" }
)
}.mapLeft { Error.SpecificError2 }
这将吞噬来自either2((的错误。
如果可能的话,我正试图找到一种方法将这个错误从either2中消除。
我知道我可以做这样的事情:
fun either5(): Either<Error, MyStrings> =
either2()
.flatMap {
Either.Right(
MyStrings(
a = "Hello",
b = it
)
)
}
但在之前调用某个东西似乎很奇怪,我需要它!
有什么想法可以改变吗?如果这是一个n00b问题,很抱歉,但我仍在努力理解函数式编程和Arrow。
谢谢。
kumbera,
在最后一个片段中,在需要它之前,您并没有真正调用它,但从语义上看,它确实是这样的。由于MyStrings
取决于either2()
的结果,但我们可以用一种更好的方式重写它,这种方式在不嵌套回调的情况下扩展得更好。
您可以通过使用Arrow的计算块来改进这些片段,这些计算块允许以安全的方式从Either
中提取值。
fun either5(): Either<Error, MyStrings> = either.eager {
MyStrings(a = "Hello", b = either2().bind())
}
这里发生的情况是,当您调用bind
时,它将返回Either.Right
的值,或者它将立即返回either2()
作为either.eager
的结果返回的Either.Left
。
还有either
计算块的suspend
变体,您可以直接用作
suspend fun either6(): Either<Error, MyString> = either {
delay(100)
MyStrings(a = "Hello", b = either2().bind())
}
我希望这能完全回答你的问题!