@jsoldi/hkt
Version:
Higher kinded types for typescript and a few utility monads.
158 lines • 4.04 kB
JavaScript
import { monad } from "../classes/monad.js";
import { monadPlus } from "../classes/monadPlus.js";
import { monoid } from "../classes/monoid.js";
import { promise } from "./promise.js";
/**
* @deprecated use `async` instead
*/
export const gen = (() => {
async function* unit(a) {
yield a;
}
async function* bind(fa, f) {
for await (const a of fa) {
yield* f(a);
}
}
async function* map(fa, f) {
for await (const a of fa) {
yield f(a);
}
}
async function* from(genlike) {
if (genlike instanceof Function) {
yield* from(genlike());
}
else if (genlike instanceof Array) {
for (const a of genlike)
yield a;
}
else {
yield await genlike;
}
}
const flat = (gen) => bind(gen, a => a);
const take = (n) => async function* (fa) {
for await (const a of fa) {
if (n-- <= 0)
break;
yield a;
}
};
const forEach = (f) => async function* (fa) {
for await (const a of fa) {
f(a);
yield a;
}
};
const toArray = async (fa) => {
const result = [];
for await (const a of fa)
result.push(a);
return result;
};
const filter = (pred) => async function* (fa) {
for await (const a of fa) {
if (pred(a))
yield a;
}
};
const takeWhile = (pred) => async function* (fa) {
for await (const a of fa) {
if (!await pred(a))
break;
yield a;
}
};
const skipWhile = (pred) => async function* (fa) {
let skip = true;
for await (const a of fa) {
if (skip && !await pred(a))
skip = false;
if (!skip)
yield a;
}
};
const distinctBy = (key) => async function* (fa) {
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) => async function* (fa) {
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 reduce = (init, f) => async function (fa) {
// 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 = async function* (fa, fb) {
yield* fa;
yield* fb;
};
const unfoldr = (f) => async function* (b) {
let next = await f(b);
while (next.right) {
let a;
[a, b] = next.value;
yield a;
next = await f(b);
}
};
const flatMapFrom = (f) => (gen) => bind(gen, a => from(f(a)));
const foldl = (f) => (b) => reduce(b, f);
const scalar = promise;
const _monadPlus = monadPlus({
...monad({
map,
unit,
bind,
}),
...monoid({
empty,
append
}),
});
return {
// ...fold<KGen, KPromise>({
// map,
// foldl,
// scalar
// }),
// scalar,
..._monadPlus,
from, // override MonadPlus implementation
take,
flat,
forEach,
toArray,
filter,
takeWhile,
skipWhile,
distinctBy,
distinct,
chunks,
reduce,
unfoldr,
flatMapFrom
};
})();
//# sourceMappingURL=gen.js.map