UNPKG

fp-ts-std

Version:

The missing pseudo-standard library for fp-ts.

59 lines (58 loc) 2.38 kB
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)), });