我很难找到一种使用 RxJava 以及箭头 ktEither
和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
作为 type返回Either<ApiError, Option<Bar>>
。
复杂性来自这样一个事实,即从返回的数据中检索到qux
所需的参数(是类型的属性)。loadBar()
Single
loadFoo()
Qux
Foo
Option<Qux>
期望的结果:
- 发生的任何s
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 observable comprehensions。但无法完全弄清楚如何让这个最终返回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()
}
任何有关如何解决此问题或重组数据类型以使其更容易的帮助/建议将不胜感激!对于许多函数式编程概念来说仍然很新。