``` //given private fun getUserRole(user: User): E...
# arrow
f
Copy code
//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 times
s
Copy code
users.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.
traverse
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.
In
0.11.0-SNAPSHOT
you could also simply do the following:
Copy code
either {
  users.map { !getUserRole(it) }
       .toSortedSet(comparator)
}
Here
!
will short-circuit on the first
Left
as well, returning it's
IError
.
j
What version are you on? This is a bug where
traverse
evaluated all elements of a sequence before it short-circuits. It should be fixed on the latest snapshot 0.10.5. @simon.vergauwen's versions also all need the latest snapshot at least 0.10.5 to be lazy, although they are nicer code^^ On 0.11 you can either use
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() } }
.
Actually never mind that, 0.10.5 should have the fixed traverse instance as well
f
users are a set, yes. Awesome, big thanks for the info!!!