Котлин когда выражение автопередача

Я хотел бы, чтобы следующий код 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 and Option.

К сожалению, я могу получить доступ только к значению первого условия "есть успех", а не ко второму условию "есть некоторые". Таким образом, я могу сделать только "result.value", тогда я получу опцию String.

Я что-то пропустил? Это сэкономит мне много внутренних вызовов ".map" и ".fold".

Обновить:

Мне нужно сначала разыграть это, что некрасиво:

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

2 ответа

Решение

Я попробовал ваш пример в 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!"
}

Я использую Kotlin 1.3.x when с синтаксисом объявления.

Вы также можете использовать Arrow API для получения аналогичного результата:

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

Здесь вам не нужно иметь else пункт в when,

Вы можете упростить сопоставление с шаблоном следующим образом:

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

Что является более исчерпывающим и не требует else альтернатива

В качестве альтернативы, если вас не волнует выбрасываемое исключение, вы можете использовать toOption на Try:

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

Однако это приводит к некоторой очевидной потере информации.

Я бы лично Try экземпляр для потребителя результата рушится Option с .map так что конечный результат имеет тип Try<String> и пусть потребитель обработает ошибку.

Тем не менее, это зависит от реального контекста проблемы.

Другие вопросы по тегам