Search code examples
kotlinarrow-kt

Kotlin arrow transform a List of failures to a Failure of a list


How can I transform the following:

List<Try<String>>

to:

Try<List<String>>

Using kotlin and the functional library arrow (0.8.2). I would like to wrap it in a custom exception. It does not matter which one of the 'String' failed.

Update:

As the below answers will suffice, but I find it really hard to read. So, I implemented the following:

Create the following function:

    fun getFailedStrings(result: List<Try<String>>): List<Failure> {
return result.fold(
    initial = listOf(),
    operation = { accumulator, nextUpdate ->
        nextUpdate.fold(
            ifSuccess = { accumulator },
            ifFailure = { accumulator + Failure(it) }
        )
    })

}

Then use the result of the function:

  return if (failedStrings.isNotEmpty()) {
      failedStrings.first() // or whatever fits your usecase
  } else {
     // strings is the initial result of List<Try<String>>
      Success(strings.mapNotNull { it.orNull() })
   }

Solution

  • If we don't care about keeping the original exceptions we could do something like this with traverse:

    val traversedTries = tries.traverse(Try.applicative(), ::identity)
    

    This will return an instance of type Try<ListK<String>> with either all the strings or the first exception it finds.

    ListK extends from List but we can optionally cast it by adding .map { it as List<String> } in the end if we need it to be Try<List<String>>

    Alternatively, if we want to split the successes and failures we can create the following function:

    fun <A> List<Try<A>>.splitSuccessFailure() : Tuple2<List<A>, List<Throwable>> =
      fold(emptyList<A>() toT emptyList<Throwable>()) { (successes, failures), it -> 
        it.fold({ successes toT (failures + it) }, { (successes + it) toT failures })  
      }
    

    Then, when we want to use it we can do the following:

    val (successes, failures) = invalidTries.splitSuccessFailure()
    

    Giving us two lists with the success values and failures respectively.