@jsoldi/hkt
Version:
Higher kinded types for typescript and a few utility monads.
120 lines • 3.88 kB
JavaScript
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