У меня есть что-то вроде этого списка List<Either<Failure, List<MyResult>>>
, и я хотел бы сгладить его до Either<Failure, List<MyResult>>
с помощью Arrow-kt, но все, что я пробовал, кажется довольно неуклюжим и в конечном итоге обходит список дважды.
Такое ощущение, что должен быть лучший способ, но я не могу понять его.
Вот надуманный пример того, что у меня есть сейчас:
val things : List<MyThing> = /* some stuff */
val results : List<Either<Failure, List<MyResult>>> = things.map { doThingThatReturnsEither(it) }
val successes : List<MyResult> = results.mapNotNull { it.orNull() }.flatten()
val firstFailure : Failure? = results.mapNotNull { it.swap().orNull() }.firstOrNull()
return firstFailure?.let {it.left()} ?: success.right()
Любые предложения приветствуются!
Бонусный вопрос: есть ли способ сократить things.map { }
, если один из них вернется с Left
?
Функция, которую вы ищете, это sequence
val res:Either<Failure, List<MyResult>> = results.sequence(Either.applicative())
.fix()
.map { it.fix() }
это приведет к короткому замыканию на первом Failure
(если есть) и вернет его слева или даст вам все MyResult
в виде списка.
fix()
и map { it.fix() }
необходимы из-за эмуляции Arrow типов более высокого порядка.
Hi Arrow 1.1.5 удалил все функции расширения. не могли бы вы предложить решение с последней библиотекой? github.com/arrow-kt/arrow-core/tree/…
@ArjunNagathankandy sequence
все еще там: arrow-kt.io/docs/apidocs/arrow-core/arrow.core/sequence.html
Мне пришлось
flatten()
дополнительноmap
получить желаемые результаты, но это намного лучше, чем то, что у меня было раньше, спасибо.