Arrow-kt:如何将 Either<E, List<Either<E,A>>> 变成 Either<E, List<B>>

Arrow-kt: how to turn an Either<E, List<Either<E,A>>> into Either<E, List<B>>

我从函数调用中收到 Either<E, List<A>>,需要将 List<A> 转换为 List<B>。每个Areturns一个Either<E,B>的变换,这样我的结果就是一个Either<E, List<Either<E,B>>>。我怎样才能把 Either<E, List<Either<E,B>>> 变成 Either<E, List<B>>,

下面是一小段代码:

fun getListOfA(): Either<Exception, List<A>> {
    TODO()
}

fun A.transformAtoB(): Either<Exception, B> {
    TODO()
}


fun getListB(): Either<Exception, List<B>> {
    return getListOfA().map {

        // this is now Either<Exception, List<Either<Exception, B>>>
        listOfA -> listOfA.map { it.transformAtoB() }

        // ????? => Either<E, List<B>>
    }
}

有一个名为 traverseEither 的函数可以让您执行此类操作。

public inline fun <E, A, B> Iterable<A>.traverseEither(f: (A) -> Either<E, B>): Either<E, List<B>>

对于 IterableA 的每个值,它将调用 f,如果所有结果都是 Either.Right,那么它将导致 Either.Right<List<B>>,否则它将导致它遇到的第一个 Either.Left<E>

所以我们可以重写您的代码段:

fun getListOfA(): Either<Exception, List<A>> = TODO()

fun A.transformAtoB(): Either<Exception, B> = TODO()

fun getListB(): Either<Exception, List<B>> =
    getListOfA().flatMap { listOfA ->

        // this is now Either<Exception, List<Either<Exception, B>>>
        listOfA.traverseEither { it.transformAtoB() }
    }

它也存在于 ValidatedOptionhttps://arrow-kt.io/docs/apidocs/arrow-core/arrow.core/kotlin.collections.-iterable/index.html#extensions-for-kotlincollectionsiterable

您还可以在 Arrow Fx 协程中找到并行变体