1

我有一些看起来像这样的代码:

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 }

这将吞噬来自 any2() 的错误。

如果可能的话,我正在尝试找到一种方法从 any2 中抛出此错误。

我知道我可以做这样的事情:

fun either5(): Either<Error, MyStrings> =
either2()
    .flatMap {
        Either.Right(
            MyStrings(
                a = "Hello",
                b = it
            )
        )
    }

但是在我需要它之前调用它似乎很奇怪!

关于如何更改 any4() 的任何想法?抱歉,如果这是一个 n00b 问题,但我仍在尝试围绕函数式编程和 Arrow 进行思考。

谢谢你。

4

1 回答 1

2

昆贝拉,

在最后一个片段中,您并没有真正在需要它之前调用它,但从语义上看它确实是这样的。由于MyStrings取决于 的结果either2(),但我们可以以更好的方式重写它,无需嵌套回调就可以更好地扩展。

您可以通过使用 Arrow 的计算块来改进这些片段,它允许以安全的方式提取值Either

fun either5(): Either<Error, MyStrings> = either.eager {
  MyStrings(a = "Hello", b = either2().bind())
}

这里发生的情况是,当您调用bind它时,它要么返回 的值Either.Right,要么立即将Either.Left返回的 byeither2()作为 的结果返回either.eager

还有一个计算块的suspend变体either,您可以直接将其用作

suspend fun either6(): Either<Error, MyString> = either {
  delay(100)
  MyStrings(a = "Hello", b = either2().bind())
}

我希望这完全回答了你的问题!

于 2022-02-06T09:51:56.317 回答