@jsoldi/hkt
Version:
Higher kinded types for typescript and a few utility monads.
55 lines • 1.91 kB
JavaScript
import { functor } from "./functor.js";
import { monadTrans } from "./transformer.js";
import { id } from "../core/utils.js";
import { pipe as _pipe } from "../core/utils.js";
const is_monad = Symbol("is_monad");
function _monad(base) {
if (is_monad in base)
return base;
return _pipe(base, base => ({
...functor({
map: (fa, f) => base.bind(fa, a => base.unit(f(a))),
...base
}),
...base
}), base => {
const lift2 = (f) => (fa, fb) => base.bind(fa, a => base.bind(fb, b => base.unit(f(a, b))));
const lift3 = (f) => (fa, fb, fc) => base.bind(fa, a => base.bind(fb, b => base.bind(fc, c => base.unit(f(a, b, c)))));
const flatMap = (f) => (fa) => base.bind(fa, f);
const flat = (ffa) => base.bind(ffa, id);
const _kleisli = (...fs) => fs.reduceRight((acc, f) => (...arg) => base.bind(f(...arg), a => acc(...[a, ...arg])), base.unit);
const _pipe = (head, ...tail) => base.bind(head, _kleisli(...tail));
const _chain = (...fs) => flatMap(_kleisli(...fs));
const runFree = (t) => {
if (t.right) {
return base.bind(t.value, runFree);
}
else {
return base.unit(t.value);
}
};
return {
[is_monad]: true,
lift2,
lift3,
flatMap,
flat,
fish: _kleisli,
chain: _chain,
pipe: _pipe,
runFree,
...base
};
});
}
_monad.trivial = {
..._monad({
unit: a => a,
bind: (fa, f) => f(fa),
map: (fa, f) => f(fa),
}),
transform: (inner) => monadTrans({ ...inner, lift: id, wrap: inner.unit })
};
/** The monad factory, providing a set of functions for working with monads. */
export const monad = _monad;
//# sourceMappingURL=monad.js.map