Fred Friis
08/19/2020, 4:32 AM//given
private fun getUserRole(user: User): Either<IError, SearchUserResponse> {
}
//this generates an explosion of calls
users
.asSequence()
.map { getUserRole(it) }
.sequence(Either.applicative())
.map { it.fix() }
.map { it.toSortedSet(comparator) }
//all we want is to call getUserRole one by one
//AND short circuit on the first error
//ie if there's 100 users and we get an error on
//the 2nd one, we don't want to call getUserRole
//another 98 timessimon.vergauwen
08/19/2020, 6:29 AMusers.traverse(Either.applicative()) { user ->
getUserRole(user)
}.map { it.fix().toSortedSet(comparator) }
I'm assuming users is of type Set? If it's of type Set then you need to first convert to a data type that guarantees order, or won't discard results like Set does.simon.vergauwen
08/19/2020, 6:30 AMtraverse is like sequence but it combines itself with the map operation, so that you can do.
List<User> -> Either<IError, List<SearchUserResponse> with a single function call.simon.vergauwen
08/19/2020, 6:32 AM0.11.0-SNAPSHOT you could also simply do the following:
either {
users.map { !getUserRole(it) }
.toSortedSet(comparator)
}
Here ! will short-circuit on the first Left as well, returning it's IError.Jannis
08/19/2020, 12:18 PMtraverse evaluated all elements of a sequence before it short-circuits. It should be fixed traverse/sequence or just straight up use the either dsl and any inline function.
If you don't want to upgrade you can probably also use the normal eitherfx dsl if sequence map is inline Either.fx { seq.map { stuff().bind() } }.Jannis
08/19/2020, 12:38 PMFred Friis
08/19/2020, 11:12 PM