import type { Eq } from "@principia/prelude/Eq"; import { empty } from "./constructors"; import { filter_ } from "./filterable"; import { elem, elem_ } from "./guards"; /** * Form the union of two sets * * @category Combinators * @since 1.0.0 */ export const union_ = (E: Eq) => { const elemE = elem(E); return (me: ReadonlySet, that: ReadonlySet) => { if (me === empty) { return that; } if (that === empty) { return me; } const r = new Set(me); that.forEach((e) => { if (!elemE(e)(r)) { r.add(e); } }); return r; }; }; /** * Form the union of two sets * * @category Combinators * @since 1.0.0 */ export const union = (E: Eq) => { const unionE_ = union_(E); return (that: ReadonlySet) => (me: ReadonlySet) => unionE_(me, that); }; /** * The set of elements which are in both the first and second set * * @category Combinators * @since 1.0.0 */ export const intersection_ = (E: Eq) => { const elemE = elem(E); return (me: ReadonlySet, that: ReadonlySet) => { if (me === empty || that === empty) { return empty; } const r = new Set(); me.forEach((e) => { if (elemE(e)(that)) { r.add(e); } }); return r; }; }; /** * The set of elements which are in both the first and second set * * @category Combinators * @since 1.0.0 */ export const intersection = (E: Eq) => { const intersectionE_ = intersection_(E); return (that: ReadonlySet) => (me: ReadonlySet) => intersectionE_(me, that); }; export const difference_ = (E: Eq) => { const elemE_ = elem_(E); return (me: ReadonlySet, that: ReadonlySet) => filter_(me, (a) => !elemE_(that, a)); }; export const difference = (E: Eq) => { const differenceE_ = difference_(E); return (that: ReadonlySet) => (me: ReadonlySet) => differenceE_(me, that); }; export const insert_ = (E: Eq) => { const elemE_ = elem_(E); return (set: ReadonlySet, a: A) => { if (!elemE_(set, a)) { const r = new Set(set); r.add(a); return r; } else { return set; } }; }; export const insert = (E: Eq) => { const insertE_ = insert_(E); return (a: A) => (set: ReadonlySet) => insertE_(set, a); }; export const remove_ = (E: Eq) => (set: ReadonlySet, a: A) => filter_(set, (ax) => !E.equals(a)(ax)); export const remove = (E: Eq) => (a: A) => (set: ReadonlySet) => remove_(E)(set, a);