I have two async function calls to external systems returning Either<Exception, Something> and need to combine their results. Being a beginner in functional programming in Arrow-Kt, I am wondering which is the best way of accomplishing this task. Below is the code, which I am currently using. It certainly works but does not really "feel" to be most straight forward. I am looking for a more "functional" style to get the result. NB: the upfront usage of the successful List result is necessary.
suspend fun getAs(): Either<Exception, List<A>> = TODO()
suspend fun getBs(): Either<Exception, List<B>> = TODO()
suspend fun doSomethingWithA(listA: List<A>): Unit = TODO()
launch {
val deferredA = async { getAs() }
val deferredB = async { getBs() }
either<Exception, List<A>> {
val listOfAs = deferredA.await()
.bimap(leftOperation = { e ->
println("special message on error for A")
e
}, rightOperation = { listA ->
doSomethingWithA(listA)
listA
})
.bind()
val listOfBs = deferredB.await().bind()
listOfAs.filter { it.someId !in listOfBs.map { it.someProperty } }
}
.map { /* handle result */ }
.handleError { /* handle error */ }
}
An alternative option would be to just use the map{}
function like so
launch {
val deferredA = async { getAs() }
val deferredB = async { getBs() }
deferredA.await()
.bimap(leftOperation = { e ->
println("special message on error for A")
e
}, rightOperation = { listA ->
doSomethingWithA(listA)
deferredB.await().map { listB ->
listA.filter { a -> a.someId !in listB.map { it.someProperty } }
}
})
.map { /* handle result */ }
.handleError { /* handle error */ }
}
The easiest way is to combine
either { }
withparZip
.either { }
allows you to extractA
fromEither<E, A>
, andparZip
is a utility function for runningsuspend
function in parallel.Here
bind()
extractsA
fromEither<E, A>
. We do this insideparZip
such that whenever aLeft
gets encountered it short-circuits theeither { }
block and by doing so, it also cancels the still running tasks inparZip
.Such that if
getAs()
returns immediately withLeft
then it becomes the output value ofeither { }
andgetBs()
gets cancelled.