技术问询:如何将Either<A,B>[]转换为Either<A[],B[]>并实现错误收集规则
简化Either数组的类型转换实现
我们需要实现一个函数,将Either<A,B>[]类型转换为Either<A[],B[]>类型,转换规则如下:
- 若数组中存在任意一个左值(错误),返回包含所有错误的左值
- 若数组中无错误,返回包含所有正确结果的右值
以下是最初的实现代码,嵌套层级较多,逻辑不够直观:
const compress = <A, B>(arr: E.Either<A, B>[]): E.Either<A[], B[]> => A.reduce( E.right([]), (acc: E.Either<A[], B[]>, v: E.Either<A, B>) => E.match( (a: A) => E.match((aar: A[]) => E.left([...aar, a]), (bar: B[]) => E.left([a]))(acc), (b: B) => E.match((aar: A[]) => E.left(aar), (bar: B[]) => E.right([...bar, b]))(acc) )(v) )(arr);
简洁实现方案
利用fp-ts内置的E.partition函数,可以直接将Either数组拆分为左值数组和右值数组,再根据左值数组是否为空返回对应结果,代码逻辑清晰且简洁:
import * as E from 'fp-ts/Either' import { pipe } from 'fp-ts/function' const compress = <A, B>(arr: E.Either<A, B>[]): E.Either<A[], B[]> => pipe( E.partition(arr), // 将Either数组拆分,得到{ left: A[], right: B[] } ({ left, right }) => left.length > 0 ? E.left(left) : E.right(right) )
方案说明
E.partition(arr):遍历输入的Either数组,自动把所有左值收集到left数组,右值收集到right数组- 检查
left数组的长度,若不为空则返回包含所有错误的左值;否则返回包含所有正确结果的右值,完全符合需求
如果不想使用pipe,也可以写成更直白的形式:
import * as E from 'fp-ts/Either' const compress = <A, B>(arr: E.Either<A, B>[]): E.Either<A[], B[]> => { const { left, right } = E.partition(arr) return left.length ? E.left(left) : E.right(right) }
内容的提问来源于stack exchange,提问作者Michael Lorton
相关产品推荐
相关产品推荐

