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

Posted

技术标签:

【中文标题】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>> 【发布时间】:2021-11-10 15:19:42 【问题描述】:

我从函数调用中收到Either&lt;E, List&lt;A&gt;&gt;,需要将List&lt;A&gt; 转换为List&lt;B&gt;。每个A的转换返回一个Either&lt;E,B&gt;,所以我的结果是一个Either&lt;E, List&lt;Either&lt;E,B&gt;&gt;&gt;。如何将Either&lt;E, List&lt;Either&lt;E,B&gt;&gt;&gt; 变成Either&lt;E, List&lt;B&gt;&gt;

如果所有转换都成功(如果单个转换失败,则应返回Either.Left) 创建一个包含所有 B 的 Either&lt;E,List&lt;B&gt;&gt;,其中转换成功并忽略失败的 AtoB 转换

下面是一个小代码sn-p:

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>>
    

【问题讨论】:

【参考方案1】:

有一个名为traverseEither 的函数允许您执行这些操作。

public inline fun &lt;E, A, B&gt; Iterable&lt;A&gt;.traverseEither(f: (A) -&gt; Either&lt;E, B&gt;): Either&lt;E, List&lt;B&gt;&gt;

对于IterableA 的每个值,它将调用f,如果所有结果都是Either.Right,则结果为Either.Right&lt;List&lt;B&gt;&gt;,否则将导致第一个Either.Left&lt;E&gt;它遇到了。

所以我们可以重写你的sn-p:

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() 
    

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

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

【讨论】:

.map 需要更改为 .flatMap 才能得到 Either>。但除此之外,这就是我一直在寻找的解决方案! 如果转换将返回 Option 而不是 Either,例如在 A.transformToB():Option 中,如何遍历? 还有traverseOptiontraverseValidated等,都可以在帖子分享的链接中找到。 很抱歉,我没有看到任何 traverseOption()。我之前阅读了链接页面,但描述中也没有 traverseOption。有一个 traverse()、traverseEither() 和 traverseValidated()。在 List 上,我只能执行 traverseEither/traverseValidated。我想在这里包含另一个库吗?我可以将 filterOption() 应用于 List 抱歉,traverseOption 仅在 0.13.31.0.0 将于 2021 年 9 月发布(写作本周晚些时候)之后添加。

以上是关于Arrow-kt:如何将 Either<E, List<Either<E,A>>> 变成 Either<E, List<B>>的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Seq[Either[A,B]] 减少为 Either[A,Seq[B]]?

如何在flutter中将Either Right初始化为空值

将 Iterable[Either[A,B]] 减少为 Either[A, Iterable[B]]

在 Flutter 中解压 Option<Either<T,T>>

LangageExt:使用 Bind() 链接两个 Either,但无法弄清楚如何使用它们创建另一个 Either

Kotlin 的 Arrow Either<Exception, X> 和事务