У меня много трудностей, чтобы найти хороший способ координировать, используя RxJava вместе с типами arrow-kt Either
и Option
.У меня есть два метода, которые оба возвращают Single<Either<ApiError, Option>
class Foo(val qux: Option<Qux>)
class Bar
class Qux
class ApiError
fun loadFoo(): Single<Either<ApiError, Option<Foo>>> {
...
}
fun loadBar(qux: Qux): Single<Either<ApiError, Option<Bar>>> {
...
}
Цель состоит в том, чтобы возвратить результат loadBar(Qux)
в RxJava Single
как тип Either<ApiError, Option<Bar>>
.
.осложнение связано с тем, что параметр qux
, необходимый для loadBar()
, извлекается из данных, выданных Single
, возвращаемых loadFoo()
(Qux
является свойством Foo
с типом Option<Qux>
).
Желаемый результат:
- Любые возникающие
ApiError
передаются абоненту Single
в Either.Left
- Если
loadFoo()
и loadBar()
возвращают Some
, это значение должно быть возвращено в составном Single
как Either.Right
- Если
loadFoo()
или loadBar()
возвращают None
, ожидаемоерезультат Either.Right(None)
Я попробовал пару вещей.Этот первый пример работает, но полученный код трудно читать из-за нескольких вложенных складок, а также из-за смешивания операторов RxJava и Either/Option
.
fun loadBarFromMaybeFoo(maybeFoo: Option<Foo>): Single<Either<ApiError, Option<Bar>>> {
return maybeFoo.flatMap { foo -> foo.qux }
.map { qux -> loadBar(qux) }
.getOrElse { Single.just(Either.Right(Option.empty())) }
}
fun doStuffToGetBar(): Single<Either<ApiError, Option<Bar>>> {
return loadFoo()
.flatMap { maybeFooOrError ->
maybeFooOrError.fold(
{ error -> Single.just(Either.Left(error)) },
{ maybeFoo -> loadBarFromMaybeFoo(maybeFoo) }
)
}
}
Вторая вещь, которую я попробовалдолжен был использовать наблюдаемые rxjava стрелки понимания .Но не мог понять, как заставить это возвращать Single<Either<ApiError, Option>
в конце.
fun doStuffToGetBar(): Single<Either<ApiError, Option<Bar>>> {
return SingleK.monadDefer().bindingCatch {
val maybeFooOrError: Either<ApiError, Option<Foo>> = loadFoo().k().bind()
val maybeQuxOrError: Either<ApiError, Option<Qux>> = maybeFooOrError.map { maybeFoo ->
maybeFoo.flatMap { it.qux }
}
// return type is Either<ApiError, Option<Either<ApiError, Option<Bar>>>>
// desired return type is Either<ApiError, Option<Bar>>
maybeQuxOrError.map { maybeQux ->
maybeQux.map { qux ->
loadBar(qux).k().bind() // this part doesn't seem good
}
}
}.value()
}
Любая помощь / совет о том, как решить эту проблему или реструктурировать типы данных, чтобы сделать это прощебудет высоко ценится!Все еще довольно плохо знаком со многими концепциями функционального программирования.