[英]Traverse/sequence and Array<Either<E, A>> into Either<Array<E>, Array<A>> in fp-ts
我有一個實體列表,即使一個失敗的驗證也會產生錯誤。 但是,我仍然想迭代整個列表並收集所有錯誤以供進一步記錄。
使用默認 Either's Applicative 的遍歷/序列將產生Either<E, A[]>
(僅遇到第一個錯誤),而不是需要Either<E[], A[]>
。
庫中是否有默認工具來實現這一點,還是可以通過編寫自定義 Applicative 來實現?
沒有直接執行此操作的 fp-ts function,但您可以使用Either
模塊中的getApplicativeValidation
:
import * as E from 'fp-ts/lib/Either'
import * as RA from 'fp-ts/lib/ReadonlyArray'
import {pipe} from 'fp-ts/lib/function'
const collectErrors = <E, A>(
xs: readonly E.Either<E, A>[]
): E.Either<readonly E[], readonly A[]> =>
pipe(
xs,
RA.traverse(E.getApplicativeValidation(RA.getSemigroup<E>()))(
E.mapLeft(RA.of)
)
)
// Left(['a', 'b'])
collectErrors([E.left('a'), E.right(1), E.left('b'))])
// Right([1, 2])
collectErrors([E.right(1), E.right(2)])
// Right([])
collectErrors([])
其工作原理是getApplicativeValidation
采用Semigroup
實例並返回可與traverse
一起使用的Applicative
實例。 applicative 實例將使用 semigroup 實例組合錯誤。
RA.traverse(
// The applicative instance for the either that will collect the errors
// into an array
E.getApplicativeValidation(
// The semigroup instance for readonly E[], which concatenates the arrays
RA.getSemigroup<E>()
)
)(
// Turn each Either<E, A> into Either<readonly E[], A> by putting each error
// inside an array so they can be concatenated
E.mapLeft(RA.of)
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.