Appendix A: Essential Functions Support

    compose

    1. function compose(...fns) {
    2. const n = fns.length;
    3. return function $compose(...args) {
    4. let $args = args;
    5. for (let i = n - 1; i >= 0; i -= 1) {
    6. $args = [fns[i].call(null, ...$args)];
    7. }
    8. return $args[0];
    9. };
    10. }

    curry

    1. // curry :: ((a, b, ...) -> c) -> a -> b -> ... -> c
    2. function curry(fn) {
    3. const arity = fn.length;
    4. if (args.length < arity) {
    5. return $curry.bind(null, ...args);
    6. }
    7. return fn.call(null, ...args);
    8. };
    9. }
    1. const either = curry((f, g, e) => {
    2. if (e.isLeft) {
    3. return f(e.$value);
    4. }
    5. return g(e.$value);
    6. });

    identity

    inspect

    1. // inspect :: a -> String
    2. function inspect(x) {
    3. if (x && typeof x.inspect === 'function') {
    4. return x.inspect();
    5. }
    6. function inspectFn(f) {
    7. return f.name ? f.name : f.toString();
    8. }
    9. function inspectTerm(t) {
    10. switch (typeof t) {
    11. case 'string':
    12. return `'${t}'`;
    13. const ts = Object.keys(t).map(k => [k, inspect(t[k])]);
    14. return `{${ts.map(kv => kv.join(': ')).join(', ')}}`;
    15. }
    16. return String(t);
    17. }
    18. }
    19. function inspectArgs(args) {
    20. return Array.isArray(args) ? `[${args.map(inspect).join(', ')}]` : inspectTerm(args);
    21. }
    22. return (typeof x === 'function') ? inspectFn(x) : inspectArgs(x);
    23. }
    1. // left :: a -> Either a b
    2. const left = a => new Left(a);

    liftA*

    1. // liftA2 :: (Applicative f) => (a1 -> a2 -> b) -> f a1 -> f a2 -> f b
    2. const liftA2 = curry((fn, a1, a2) => a1.map(fn).ap(a2));

    maybe

    1. // maybe :: b -> (a -> b) -> Maybe a -> b
    2. const maybe = curry((v, f, m) => {
    3. if (m.isNothing) {
    4. return v;
    5. }
    6. return f(m.$value);
    7. });
    1. // nothing :: () -> Maybe a
    2. const nothing = () => Maybe.of(null);

    reject

    1. // reject :: a -> Task a b