Search code examples
kotlinarrow-kt

kotlin when expression autocast


I would like the following kotlin code to work:

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!"
}

I use the arrow library for the Try and Option monad.

Unfortunately, I can only access the value of the first condition "is Success" and not the second condition "is Some". So, I can only do "result.value", I then get an Option of String.

Am I missing something? This will save me alot of inner ".map" and ".fold" calls.

Update:

I need to cast it first, which is ugly:

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

Solution

  • I tried your example in IntelliJ with Kotlin 1.3.21. It shows the reason of the problem: enter image description here

    You need to extract the result.value as a variable to make it work. I found the following snippet to solve it

    
    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!"
    }
    

    I use Kotlin 1.3.x when with declaration syntax.

    You may also use Arrow API to get similar result:

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

    Here you do not need to have the else clause in when.