如何在 Kotlin 中有效地展平任何一个列表

Jam*_*mes 1 kotlin arrow-kt

我有一个类似这样的列表,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() 
Run Code Online (Sandbox Code Playgroud)

欢迎任何建议!

额外问题:things.map { }如果其中一个返回 ,是否有捷径Left

Lor*_*nMK 5

您正在寻找的功能是 sequence

val res:Either<Failure, List<MyResult>> = results.sequence(Either.applicative())
    .fix()
    .map { it.fix() }
Run Code Online (Sandbox Code Playgroud)

这将在第一个Failure(如果有)上短路并将其返回到左边,或者给你所有的MyResult列表。

fix()map { it.fix() },是因为较高的kinded类型的箭的仿真的需要。

  • 我必须在额外的“map”中进行“flatten()”才能获得我想要的结果,但这比我之前得到的要好得多,谢谢。 (2认同)