2

我希望以下 kotlin 代码能够正常工作:

val result: Try<Option<String>> = Success(Some("test"))

val test = when {
    result is Success && result.value is Some -> result.value.t // not working
    result is Success && result.value is None -> "Empty result"
    result is Failure -> "Call failed!"
    else -> "no match!"
}

我将箭头库用于 Try 和 Option monad。

不幸的是,我只能访问第一个条件“is Success”的值,而不能访问第二个条件“is Some”的值。所以,我只能做“result.value”,然后我得到一个字符串选项。

我错过了什么吗?这将为我节省很多内部“.map”和“.fold”调用。

更新:

我需要先投射它,这很难看:

result is Success && result.value is Some -> (result.value as Some<String>).t
4

2 回答 2

3

我在 IntelliJ 中使用 Kotlin 1.3.21 尝试了您的示例。它显示了问题的原因: 在此处输入图像描述

您需要将 提取result.value为变量以使其工作。我找到了以下代码片段来解决它


val result: Try<Option<String>> = Success(Some("test"))

val test = when (result) {
    is Success -> when(val value = result.value) {
        is Some -> value.t
        is None -> "None"
    }
    is Failure -> "Call failed!"
    else -> "no match!"
}

when我使用带有声明语法的Kotlin 1.3.x。

您也可以使用 Arrow API 来获得类似的结果:

val test = result.fold(
    ifSuccess = { it.getOrElse { "None" }},
    ifFailure = { "Call failed!" }
)

在这里,您不需要将else子句 in when

于 2019-02-14T18:10:27.917 回答
0

您可以像这样简化模式匹配:

val test = result
  .map { it.getOrElse { "Empty result"} }
  .getOrElse { "Call failed!" }

哪个更详尽,不需要else替代方案

或者,如果您不关心抛出的异常,您可以toOption使用Try

val test = result
  .toOption()
  .getOrElse { "No value!!" }

但是,这有一些明显的信息丢失。

我个人会将Try实例冒泡给结果的消费者,Option用 a折叠内部,.map以便最终结果是类型Try<String>并让消费者处理错误。

但是,这在很大程度上取决于问题的实际背景。

于 2019-02-14T18:09:10.220 回答