streetsofboston
04/01/2020, 1:00 PMfun getAccountKeys(): Single<Either<List<AccountKey>>>
and
fun getAccount(key: AccountKey): Single<DataModelResult<Account>>
We’d like to create the following function, that will use the two above
fun getAccounts(): Single<DataModelResult<List<Account>>>
(DataModelResult<T>
= Either<DataError, T>
)
This is one implementation of `getAccounts()`:
val result: Single<DataModelResult<List<Account>>> =
getAccountKeys()
.flatMap { listOfKeys: DataModelResult<List<AccountKey>> ->
val rxOfKeys: DataModelResult<Observable<AccountKey>> =
listOfKeys.map { Observable.fromIterable(it) }
val rxOfAccounts: DataModelResult<Observable<DataModelResult<Account>>> =
rxOfKeys.map { rxKey -> rxKey.flatMapSingle(::getAccount) }
val rxOfListOfAccounts: DataModelResult<Single<List<DataModelResult<Account>>>> =
rxOfAccounts.map { it.toList() }
val single: Single<DataModelResult<List<Account>>> = when (rxOfListOfAccounts) {
is Either.Left -> Single.just(rxOfListOfAccounts)
is Either.Right -> rxOfListOfAccounts.b.map { listOfAccounts: List<DataModelResult<Account>> ->
listOfAccounts.fold(emptyList<Account>().just(), ::concat)
}
}
single
}
return result
.. and this top-level concat function ..
fun <L, T> concat(result: Either<L, List<T>>, item: Either<L, T>): Either<L, List<T>> =
result.flatMap { list -> item.map { list + it } }
Is this the way to go or is there a more Arrow/Functional way to go (we use Arrow version 0.9.0
)?
Thank you!pakoito
04/01/2020, 1:27 PMpakoito
04/01/2020, 1:28 PMgetAccountKeys()
.toObservable()
.flatMap {
it.fold({ Observable.empty() }, { Observable.fromIterable(it) })
}.flatMap {
getAccount(it).toObservable()
}.toList()
.toSingle()
pakoito
04/01/2020, 1:28 PMpakoito
04/01/2020, 1:29 PMpakoito
04/01/2020, 1:31 PMList<Either<E, List<A>>>
then
list.map {
it.fold({ Observable.empty() }, { Observable.fromIterable(it) })
}
and I believe there’s an operator to create an Observable from a list of Observablespakoito
04/01/2020, 1:32 PMgetAccount
on each, collect to Single afterwardspakoito
04/01/2020, 1:33 PMconcatMap
if you want to assure correct orderingstreetsofboston
04/01/2020, 1:42 PMSingle<List<DataModelResult<Account>>>
,
We’d need a Single<DataModelResult<List<Account>>>
instead (swapped the List and the DataModelResult 🙂 )streetsofboston
04/01/2020, 1:47 PMDataError
(if any was raised) from the getAccountKeys()
call, since it was folded into a Observable.empty()….pakoito
04/01/2020, 3:41 PMDataModelResult
?streetsofboston
04/01/2020, 3:52 PMtypealias DataModelResult<T> = Either<DataError, T>
pakoito
04/01/2020, 4:02 PMpakoito
04/01/2020, 4:03 PMSingle<Either<List<AccountKey>>>
is Left
, is the whole operation Left
or not?pakoito
04/01/2020, 4:04 PMgetAccountKeys()
.toObservable()
.flatMap {
it.fold({
Observable.just(it.left())
}, {
Observable.fromIterable(it)
.flatMap {
getAccount(it).toObservable()
}.toList()
.map { it.right() }
})
}
.toSingle()
pakoito
04/01/2020, 4:04 PMstreetsofboston
04/01/2020, 4:08 PMpakoito
04/01/2020, 7:05 PMpakoito
04/01/2020, 7:05 PMpakoito
04/01/2020, 7:05 PM