UNPKG

@jsoldi/hkt

Version:

Higher kinded types for typescript and a few utility monads.

120 lines 3.88 kB
import { monadTrans } from "../classes/transformer.js"; import { monadPlus } from "../classes/monadPlus.js"; import { traversable } from "../classes/traversable.js"; import { foldable } from "../classes/foldable.js"; import { unfoldable } from "../classes/unfoldable.js"; import { monoid } from "../classes/monoid.js"; /** The array module. */ export const array = (() => { const filter = (predicate) => { return (items) => items.filter(predicate); }; const foldl = (f) => (b) => (fa) => fa.reduce(f, b); const foldr = (f) => (b) => (fa) => fa.reduceRight((a, b) => f(b, a), b); const _unfold = (f) => (b) => { const result = []; let next = f(b); while (next.right) { let a; [a, b] = next.value; result.push(a); next = f(b); } return result; }; const chunk = (size) => (fa) => { if (size < 1) throw new Error('Invalid chunk size'); const result = []; for (let i = 0; i < fa.length; i += size) result.push(fa.slice(i, i + size)); return result; }; const distinctBy = (f) => (fa) => { const result = []; const keys = new Set(); for (const a of fa) { const b = f(a); if (!keys.has(b)) { keys.add(b); result.push(a); } } return result; }; // Promises run one by one, not in parallel const mapAsync = (f) => async (fa) => { const result = []; for (const a of fa) result.push(await f(a)); return result; }; const take = (n) => (fa) => n >= 0 ? fa.slice(0, n) : fa.slice(Math.max(fa.length + n, 0)); const skip = (n) => (fa) => n >= 0 ? fa.slice(n) : fa.slice(0, Math.max(fa.length + n, 0)); const map = (fa, f) => fa.map(f); const unit = (a) => [a]; const bind = (fa, f) => fa.flatMap(f); const empty = () => []; const append = (fa, fb) => fa.concat(fb); const zip = (fa, fb) => Array.from({ length: Math.min(fa.length, fb.length) }, (_, i) => [fa[i], fb[i]]); const _traversable = traversable({ traverse: (m) => (f) => (ta) => ta.reduceRight((acc, a) => m.lift2((b, bs) => [b, ...bs])(f(a), acc), m.unit([])) }); const _monadPlus = monadPlus({ map, unit, bind, empty, append, }); const _foldable = foldable({ map, foldl, }); const transform = (m) => { const __monadTrans = monadTrans({ map: (fa, f) => m.map(fa, a => a.map(f)), unit: a => m.unit([a]), bind: (fa, f) => m.bind(fa, ae => m.map(_traversable.sequence(m)(ae.map(f)), a => a.flat())), lift: a => m.map(a, a => [a]), wrap: a => m.unit(a), }); const __monoid = monoid({ empty: () => m.unit([]), append: (fa, fb) => m.bind(fa, a => a.length === 0 ? fb : m.map(fb, b => a.concat(b))) }); const __foldable = _foldable.liftFoldUnder(m); return { ...__monadTrans, ...__foldable, ...monadPlus({ append: __monoid.append, bind: __monadTrans.bind, empty: __monoid.empty, unit: __monadTrans.unit, }), }; }; return { ..._traversable, ..._foldable, ...unfoldable({ map, unfold: _unfold, }), ..._monadPlus, filter, transform, foldl, foldr, chunks: chunk, distinctBy, mapAsync, take, skip, zip, liftMonoid: transform, // Override default to make it short-circuit on append sequence: _traversable.sequence, }; })(); //# sourceMappingURL=array.js.map