Hi! Given I have 2 `Either` of type `<List<E...
# arrow
p
Hi! Given I have 2
Either
of type
<List<Error>, Success>>
, how could I collect both of their lefts (if both are left). My setup looks like this:
Copy code
import arrow.core.Either

data class Error(val message: String)
data class Success(val data: Int)
data class SuccessSum(val success1: Success?, val success2: Success?)

fun myFunction(): Either<List<Error>, SuccessSum> {
    val responseA = someNetworkCall()
    val responseB = someNetworkCall()

    return TODO()
}


fun someNetworkCall(aGivenParameter: Int = 1): Either<List<Error>, Success> {
    TODO()
}
and I have the following possibilities regarding my return type: it can either be: • a list of errors originating from the first response • a list of errors originating from the second response • a list of errors originating from both responses •
SuccessSum
, my happy path Is there any way to check if both eithers are null and if they are, merge their left values together into one list? My happy path would then look like that:
Copy code
fun myFunction(): Either<List<Error>, SuccessSum> {
    val responseA = someNetworkCall()
    val responseB = someNetworkCall()

    /* Guard Clause checking for lefts here */

    return SuccessSum(
        success1 = responseA.orNull(),
        success2 = responseB.orNull()
    )
}
That’s at least my initial idea. I guess
Validated
could be a better option but I didn’t look into it yet. Thanks in advance! 🙂
r
Hi @Philipp Mayer if you have two network calls that return Either you can turn them
toValidatedNel
and
zip
them together as shown in the https://arrow-kt.io/docs/patterns/error_handling/ in order to accumulate errors. Alternatively you may have your network calls return
ValidatedNel
instead of
Either
and then you can also use the
bind
in
either
blocks to treat the
Validated
values as if they where
Either
values.
p
Thanks a lot for your input @raulraja. I worked through the example and am now close to a solution (that’s what I hope at least 😄 ) My solution now looks like that:
Copy code
import arrow.core.Either
import arrow.core.ValidatedNel
import arrow.core.zip

data class Error(val message: String)
data class Success(val data: Int)
data class SuccessSum(val success1: Success?, val success2: Success?)

//my network call is now returning ValidatedNel<List<Error>, Success>
//this function merges both responses into an either
infix fun ValidatedNel<List<Error>, Success>.mergeWith(
    leaseResponse: ValidatedNel<List<Error>, Success>,
): Either<List<Error>, SuccessSum> =
    zip(leaseResponse) { firstSuccess, secondSuccess -> SuccessSum(firstSuccess, secondSuccess) }
        .mapLeft { it.flatten() }
        .toEither()
The thing that I’d like to remove is the
mapLeft
+ ultimately returning an
Nel<Error>
instead of a
List<Error>
. Any hints on that?
r
You can then simplify it to not use a
List
which is not correct since you can’t never have an empty List of Errors, you either have errors or you don’t and it could be encoded like:
ValidatedNel
already implies the left is a
NonEmptyList
so
ValidatedNel<List…
is redundant and can be avoided. Your network services should just return
ValidatedNel<Error, ..>
🤘 1
or
Validated<NonEmptyList<Error>, ...>
which is the same
p
Oh it’s so obvious. I knew I wanted a NEL but wasn’t sure how to form one from the List. Well, ofc simply create one in the network call. Sometimes it’s the easiest things..
Thanks a lot @raulraja!
r
no problem, Nel also has
unsafeFromList
for cases where the list is handed to you and you are sure it has something
p
uhhh, good to know!
r
but if you are in control definetly use the Nel from the beginning