fp-ts-std
Version:
The missing pseudo-standard library for fp-ts.
59 lines (58 loc) • 2.38 kB
JavaScript
import { fromEquals } from "fp-ts/Eq";
import * as O from "fp-ts/Option";
import { fromCompare } from "fp-ts/Ord";
import * as Tuple from "fp-ts/Tuple";
import { flow, identity, pipe } from "fp-ts/function";
import { mapBoth as _mapBoth } from "./Bifunctor";
import { fork } from "./Function";
import * as L from "./Lazy";
import { isNonNegative, isValid, multiply } from "./Number";
import { EQ } from "./Ordering";
import { allPass } from "./Predicate";
export const dup = fork([identity, identity]);
export const toFst = (f) => fork([f, identity]);
export const toSnd = (f) => fork([identity, f]);
export function traverseToFst(F) {
return g => x => F.map(g(x), y => [y, x]);
}
export function traverseToSnd(F) {
return g => x => F.map(g(x), y => [x, y]);
}
export const withFst = (x) => (y) => [x, y];
export const withSnd = (x) => (y) => [y, x];
export const create = identity;
export const mapBoth = _mapBoth(Tuple.Bifunctor);
export const fanout = f => g => fork([f, g]);
export const getEq = (EA) => (EB) => fromEquals(([xa, xb], [ya, yb]) => EA.equals(xa, ya) && EB.equals(xb, yb));
export const getOrd = (OA) => (OB) => fromCompare(([xa, xb], [ya, yb]) => {
const a = OA.compare(xa, ya);
return a === EQ ? OB.compare(xb, yb) : a;
});
export const getBounded = (BA) => (BB) => ({
...getOrd(BA)(BB),
top: [BA.top, BB.top],
bottom: [BA.bottom, BB.bottom],
});
export const getEnum = (EA) => (EB) => ({
...getBounded(EA)(EB),
succ: ([a, b]) => EA.equals(a, EA.top)
? pipe(EB.succ(b), O.map(withFst(EA.bottom)))
: pipe(EA.succ(a), O.map(withSnd(b))),
pred: ([a, b]) => EA.equals(a, EA.bottom)
? pipe(EB.pred(b), O.map(withFst(EA.top)))
: pipe(EA.pred(a), O.map(withSnd(b))),
toEnum: flow(O.fromPredicate(allPass([isValid, isNonNegative, Number.isInteger])), O.chain(n => {
const ac = L.execute(EA.cardinality);
const bc = L.execute(EB.cardinality);
if (n > ac + bc)
return O.none;
return pipe(O.of(withFst), O.ap(EA.toEnum(n % ac)), O.ap(EB.toEnum(Math.floor(n / ac))));
})),
fromEnum: ([a, b]) => {
const ai = EA.fromEnum(a);
const bi = EB.fromEnum(b);
const ac = L.execute(EA.cardinality);
return (ac - 1) * bi + ai + bi;
},
cardinality: pipe(L.of(multiply), L.ap(EA.cardinality), L.ap(EB.cardinality)),
});