0

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() })
   }
4

2 回答 2

3

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.

于 2019-05-22T16:10:19.093 回答
1

this seems to work:

 fun convert(input: List<Try<String>>): Try<List<String>> =
    input.fold(Try.just(emptyList())) { acc, i ->
        acc.flatMap { list ->
            i.flatMap {
                Try.just(list + it)
            }
        }
    }
于 2019-05-22T16:08:08.640 回答