Home > Software engineering >  How to convert kotlin Result type from List<Result<T>> to Result<List<T>>
How to convert kotlin Result type from List<Result<T>> to Result<List<T>>

Time:11-23

I have List<Result<String>> and I would like to convert it to Result<List<String>>. I understand that List<Result<String>> could have both failure and successful results but I would like to terminate in the first failure.

CodePudding user response:

If you want to have a failure as soon there is one Result that is a failure you can do this :

fun <T> List<Result<T>>.toResult() = if (any { it.isFailure }) {
        Result.failure<List<Result<Any>>>(Throwable("A result has errors"))
    } else {
        Result.success(map { it.getOrNull() })
    }

With this code, you get a failure as soon as there is one value has a failure.

Or if you don't care handling the error yourself :

fun <T> List<Result<T>>.toResult() = runCatching {
    Result.success(map { it.getOrThrow() })
}

CodePudding user response:

In most libraries this function is known as sequence. Kotlin's Arrow library implements it for its implementation of the type Either, which is a generalization of Result: https://arrow-kt.io/docs/apidocs/arrow-core/arrow.core/sequence.html

With Arrow's Either you would write:

val xs: List<Result<String>> = ...
val ys: Result<List<String>> = xs.sequence()

The Kotlin stdlib does not seem to have it. You could define it as an extension method using getOrThrow, catching any thrown Throwable and wrapping in a Resultagain:

fun <T> List<Result<T>>.sequence(): Result<List<T>> = try {
    Result.success(this.map { it.getOrThrow() })
  }
  catch (e:Throwable) { Result.failure(e) }
  • Related