使用 fp-ts 删除 Either 数组中的重复项
Remove duplicates in array of Either with fp-ts
使用 fp-ts
在函数式编程中删除 Either 数组重复项的最佳方法是什么?
这是我的尝试:
import { either as E, pipeable as P } from "fp-ts";
import { flow } from "fp-ts/lib/function";
interface IItem {
type: "VALID" | "INVALID";
value: string;
}
// Building some fake data
const buildItem = (value?: string): E.Either<unknown, string> =>
value != null ? E.right(value) : E.left({ type: "INVALID", value: "" });
// We will always have an array of Either
const items = [
buildItem("aa"),
buildItem("ab"),
buildItem(),
buildItem("ac"),
buildItem("ab"),
buildItem("ac"),
buildItem(),
buildItem("aa")
];
const checkList: string[] = [];
export const program = flow(
() => items,
x =>
x.reduce(
(acc, item) =>
P.pipe(
item,
E.chain(value => {
if (checkList.indexOf(value) < 0) {
checkList.push(value);
return E.right({ type: "VALID", value: value } as IItem);
}
return E.left({ type: "INVALID", value: value } as IItem);
}),
v => acc.concat(v)
),
[] as E.Either<unknown, IItem>[]
)
);
一般来说,在 fp-ts
中,您可以使用 fp-ts/lib/Array
中的 uniq
从 Array<A>
中删除重复项。给定一个 Eq<A>
和一个 Array<A>
它将 return 一个 Array<A>
其中所有 A
都是唯一的。
在您的情况下,您似乎想要对 Array<Either<IItem, IItem>>
进行重复删除。这意味着,为了使用 uniq
,您将需要一个 Eq<Either<IItem, IItem>>
的实例。获得它的方法是使用 fp-ts/lib/Either
中的 getEq
。它要求您为 Either
参数化的每种类型提供一个 Eq
实例,一个用于左侧情况,另一个用于右侧情况。因此,对于 Either<E, R>
,getEq
将采用 Eq<E>
和 Eq<R>
并为您提供 Eq<Either<E, R>>
。在您的情况下,E
和 R
是相同的(即 IItem
),因此您只需使用相同的 Eq<IItem>
实例两次。
您想要的 Eq<IItem>
实例很可能如下所示:
// IItem.ts |
//-----------
import { Eq, contramap, getStructEq, eqString } from 'fp-ts/lib/Eq'
export interface IItem {
type: "VALID" | "INVALID";
value: string;
}
export const eqIItem: Eq<IItem> = getStructEq({
type: contramap((t: "VALID" | "INVALID"): string => t)(eqString),
value: eqString
})
完成后,您可以像这样使用 uniq
删除 Array<Either<IItem, IItem>>
的重复数据:
// elsewhere.ts |
//---------------
import { array, either } from 'fp-ts'
import { Either } from 'fp-ts/lib/Either'
import { IItem, eqIItem } from './IItem.ts'
const items: Array<Either<IItem, IItem>> = []
const uniqItems = uniq(either.getEq(eqIItem, eqIItem))(items)
uniqItems
常量将是一个 Array<Either<IItem, IItem>>
,其中没有两个 Either<IItem, IItem>
是 "equal",如 Eq<Either<IItem, IItem>>
所定义。
使用 fp-ts
在函数式编程中删除 Either 数组重复项的最佳方法是什么?
这是我的尝试:
import { either as E, pipeable as P } from "fp-ts";
import { flow } from "fp-ts/lib/function";
interface IItem {
type: "VALID" | "INVALID";
value: string;
}
// Building some fake data
const buildItem = (value?: string): E.Either<unknown, string> =>
value != null ? E.right(value) : E.left({ type: "INVALID", value: "" });
// We will always have an array of Either
const items = [
buildItem("aa"),
buildItem("ab"),
buildItem(),
buildItem("ac"),
buildItem("ab"),
buildItem("ac"),
buildItem(),
buildItem("aa")
];
const checkList: string[] = [];
export const program = flow(
() => items,
x =>
x.reduce(
(acc, item) =>
P.pipe(
item,
E.chain(value => {
if (checkList.indexOf(value) < 0) {
checkList.push(value);
return E.right({ type: "VALID", value: value } as IItem);
}
return E.left({ type: "INVALID", value: value } as IItem);
}),
v => acc.concat(v)
),
[] as E.Either<unknown, IItem>[]
)
);
一般来说,在 fp-ts
中,您可以使用 fp-ts/lib/Array
中的 uniq
从 Array<A>
中删除重复项。给定一个 Eq<A>
和一个 Array<A>
它将 return 一个 Array<A>
其中所有 A
都是唯一的。
在您的情况下,您似乎想要对 Array<Either<IItem, IItem>>
进行重复删除。这意味着,为了使用 uniq
,您将需要一个 Eq<Either<IItem, IItem>>
的实例。获得它的方法是使用 fp-ts/lib/Either
中的 getEq
。它要求您为 Either
参数化的每种类型提供一个 Eq
实例,一个用于左侧情况,另一个用于右侧情况。因此,对于 Either<E, R>
,getEq
将采用 Eq<E>
和 Eq<R>
并为您提供 Eq<Either<E, R>>
。在您的情况下,E
和 R
是相同的(即 IItem
),因此您只需使用相同的 Eq<IItem>
实例两次。
您想要的 Eq<IItem>
实例很可能如下所示:
// IItem.ts |
//-----------
import { Eq, contramap, getStructEq, eqString } from 'fp-ts/lib/Eq'
export interface IItem {
type: "VALID" | "INVALID";
value: string;
}
export const eqIItem: Eq<IItem> = getStructEq({
type: contramap((t: "VALID" | "INVALID"): string => t)(eqString),
value: eqString
})
完成后,您可以像这样使用 uniq
删除 Array<Either<IItem, IItem>>
的重复数据:
// elsewhere.ts |
//---------------
import { array, either } from 'fp-ts'
import { Either } from 'fp-ts/lib/Either'
import { IItem, eqIItem } from './IItem.ts'
const items: Array<Either<IItem, IItem>> = []
const uniqItems = uniq(either.getEq(eqIItem, eqIItem))(items)
uniqItems
常量将是一个 Array<Either<IItem, IItem>>
,其中没有两个 Either<IItem, IItem>
是 "equal",如 Eq<Either<IItem, IItem>>
所定义。