UNPKG

@jsoldi/hkt

Version:

Higher kinded types for typescript and a few utility monads.

165 lines 4.77 kB
import { monad } from "../classes/monad.js"; import { fold } from "../classes/fold.js"; import { monadPlus } from "../classes/monadPlus.js"; import { monoid } from "../classes/monoid.js"; import { unfold } from "../classes/unfold.js"; import { task } from "./task.js"; /** The `Async` module, providing a set of functions to work with `Async` instances, which are functions that return an `AsyncGenerator` */ export const async = (() => { const fun = (asyncLike) => (...args) => async function* () { const getGen = async (al, ...as) => { return await (typeof al !== 'function' ? al : getGen(al(...as))); }; for await (const a of await getGen(asyncLike, ...args)) yield a; }; const unit = a => async function* () { yield a; }; const bind = (fa, f) => async function* () { for await (const a of fa()) { for await (const b of fun(f)(a)()) yield b; } }; const flatMap = f => fa => bind(fa, f); const map = (fa, f) => async function* () { for await (const a of fa()) yield f(a); }; const from = (asyncLike, ...args) => async function* () { for await (const a of fun(asyncLike)(...args)()) yield a; }; const flat = fa => async function* () { for await (const a of fa()) yield* a(); }; const take = n => fa => async function* () { for await (const a of fa()) { if (n-- <= 0) break; yield a; } }; const toArray = (fa) => async () => { const result = []; for await (const a of fa()) result.push(a); return result; }; const filter = (pred) => (fa) => async function* () { for await (const a of fa()) { if (pred(a)) yield a; } }; const takeWhile = pred => fa => async function* () { for await (const a of fa()) { if (!await pred(a)) break; yield a; } }; const skipWhile = pred => fa => async function* () { let skip = true; for await (const a of fa()) { if (skip && !await pred(a)) skip = false; if (!skip) yield a; } }; const distinctBy = (key) => (fa) => async function* () { const keys = new Set(); for await (const a of fa()) { const k = key(a); if (!keys.has(k)) { keys.add(k); yield a; } } }; const distinct = (fa) => distinctBy(a => a)(fa); const chunks = (size) => (fa) => async function* () { let chunk = []; for await (const a of fa()) { chunk.push(a); if (chunk.length === size) { yield chunk; chunk = []; } } if (chunk.length > 0) yield chunk; }; const foldl = f => init => fa => async () => { // Can't directly modify init because it'd modify it for all passed generators let acc = init; for await (const a of fa()) acc = f(acc, a); return acc; }; const empty = () => async function* () { }; const append = (fa, fb) => async function* () { yield* fa(); yield* fb(); }; const _unfold = (f) => (b) => async function* () { let next = await task.fun(f)(b)(); while (next.right) { let a; [a, b] = next.value; yield a; next = await task.fun(f)(b)(); } }; const zip = (fa, fb) => async function* () { const a = fa(); const b = fb(); while (true) { const [aVal, bVal] = await Promise.all([a.next(), b.next()]); if (aVal.done || bVal.done) break; yield [aVal.value, bVal.value]; } }; const scalar = task; return { ...fold({ map, foldl, scalar: scalar }), ...unfold({ map, unfold: _unfold, scalar: scalar }), ...monadPlus({ ...monad({ map, unit, bind, flatMap, }), ...monoid({ empty, append }), }), scalar: scalar, flatMap, fun: fun, from, // override MonadPlus implementation take, flat, toArray, filter, takeWhile, skipWhile, distinctBy, distinct, chunks, zip, }; })(); //# sourceMappingURL=async.js.map