@jsoldi/hkt
Version:
Higher kinded types for typescript and a few utility monads.
51 lines • 1.76 kB
JavaScript
import { fold } from "./fold.js";
import { monad } from "./monad.js";
import { chain, pipe } from "../core/utils.js";
const is_foldable = Symbol("is_foldable");
/** Creates an `IFoldable` from an `IFoldableBase`. */
export function foldable(base) {
if (is_foldable in base)
return base;
return pipe(base, base => ({
...fold({
scalar: monad.trivial,
...base,
}),
scalar: monad.trivial,
...base
}), base => {
/** Passed monad must transform from $<M, T> to $<G, $<M, T>> given G */
const liftFoldOver = (m) => {
const _m = monad(m);
return fold({
map: (fma, f) => base.map(fma, _m.fmap(f)),
scalar: _m, //: m.transform(base.scalar),
foldl: f => b => base.foldl(_m.lift2(f))(_m.unit(b)),
});
};
/** Passed monad must transform from $<M, T> to $<M, $<G, T>> given G */
const liftFoldUnder = (m) => {
const _m = monad(m);
return fold({
map: (fa, f) => _m.map(fa, base.fmap(f)),
scalar: _m, //: m.transform(base.scalar),
foldl: f => b => _m.fmap(base.foldl(f)(b))
});
};
const nestFold = (m) => {
return fold({
map: (fa, f) => base.map(fa, ma => m.map(ma, f)),
foldl: f => chain(m.scalar.unit, base.foldl((nb, ma) => m.scalar.bind(nb, b2 => m.foldl(f)(b2)(ma)))),
scalar: m.scalar
});
};
return {
[is_foldable]: true,
nestFold,
liftFoldOver,
liftFoldUnder,
...base
};
});
}
//# sourceMappingURL=foldable.js.map