UNPKG

@jsoldi/hkt

Version:

Higher kinded types for typescript and a few utility monads.

95 lines 3.05 kB
import { pipe } from "../core/utils.js"; import { monad } from "../classes/monad.js"; import { monadTrans } from "../classes/transformer.js"; /** The either module with no fixed left type. */ const core = { of: () => eitherOf(), right: (b) => ({ right: true, value: b }), left: (a) => ({ right: false, value: a }), either: (onLeft, onRight) => (fa) => fa.right ? onRight(fa.value) : onLeft(fa.value), bimap: (onLeft, onRight) => (fa) => fa.right ? core.right(onRight(fa.value)) : core.left(onLeft(fa.value)), lefts: (fa) => { const result = []; for (const a of fa) { if (!a.right) result.push(a.value); } return result; }, rights: (fa) => { const result = []; for (const a of fa) { if (a.right) result.push(a.value); } return result; }, or: b => fa => fa.right ? fa : b, and: b => fa => fa.right ? b : fa, else: b => fa => fa.right ? fa.value : b(), isLeft: (fa) => !fa.right, isRight: (fa) => fa.right, fromLeft: (a) => (fa) => fa.right ? a : fa.value, fromRight: (b) => (fa) => fa.right ? fa.value : b, partition: (fa) => { const result = { lefts: [], rights: [] }; for (const a of fa) { if (a.right) result.rights.push(a.value); else result.lefts.push(a.value); } return result; }, try: (onTry, onCatch) => { try { return core.right(onTry()); } catch (e) { return core.left(onCatch?.(e) ?? e); } }, tryAsync: async (onTry, onCatch) => { try { return core.right(await onTry()); } catch (e) { return core.left(await onCatch?.(e) ?? e); } }, throwLeft: (fa) => { if (!fa.right) throw fa.value; return fa.value; }, throwRight: (fa) => { if (fa.right) throw fa.value; return fa.value; } }; /** Creates an `IEither` with a fixed left type. */ function eitherOf() { return pipe(core, base => ({ ...monad({ unit: base.right, bind: (fa, f) => fa.right ? f(fa.value) : fa, }), ...base }), base => ({ append: (fa, fb) => fa.right ? fa : fb, transform: (outer) => { return monadTrans({ map: (fa, f) => outer.map(fa, a => base.map(a, f)), unit: (a) => outer.unit(base.right(a)), bind: (fa, f) => outer.bind(fa, a => a.right ? f(a.value) : outer.unit(a)), lift: (a) => outer.map(a, base.right), wrap: a => outer.unit(a), }); }, ...base })); } /** The `either` module, providing a set of functions for working with `Either` values. The left type is fixed to `any`. To change the left type, call the `of` function. */ export const either = eitherOf(); //# sourceMappingURL=either.js.map