type Action = (v: T) => G; //NOTE: type definition not used. Perhaps use if it makes the actual object readable. type Fun = (value: T) => { map: (action: Action) => Fun; apply: (action: Action) => Fun; run: (action: Action) => Fun; if: ( predicate: Action, t: Action, f: Action ) => Fun; get: () => T; }; /** * Entry point for functional * operations on a given value. * @param value */ export const fun = (value: T) => ({ /** * The given function should * map the valeu to another * vlaue of different type * @param */ map: (action: Action) => fun(action(value)), /** * The given function should * map the valeu to another * vlaue of the same type */ apply: (action: Action) => fun(action(value)), /** * Runs the given function */ run: (action: Action) => { action(value); return fun(value); }, //NOTE: perhaps both `t` and `e` should have to return the same type for predictability? not sure. if: ( predicate: Action, t: Action, e: Action ) => predicate(value) ? fun(t(value)) : fun(e(value)), /** * Returns the value back */ get: () => value, });