Skip to content

Latest commit

 

History

History
154 lines (108 loc) · 2.87 KB

appendix_a-es.md

File metadata and controls

154 lines (108 loc) · 2.87 KB

Apéndice A: Funciones Esenciales de Soporte

En este apéndice, encontrarás algunas implementaciones básicas en Javascript de varias funciones descritas en el libro. Ten en cuenta que estas implementaciones pueden no ser las más rápidas o las más eficientes; tienen únicamente una finalidad educativa.

Para encontrar funciones más preparadas para un entorno en producción, échale un vistazo a ramda, lodash, o folktale.

Ten en cuenta que algunas funciones también hacen referencia a estructuras algebraicas definidas en el Apéndice B

always

// always :: a -> b -> a
const always = curry((a, b) => a);

compose

// compose :: ((y -> z), (x -> y),  ..., (a -> b)) -> a -> z
const compose = (...fns) => (...args) => fns.reduceRight((res, fn) => [fn.call(null, ...res)], args)[0];

curry

// curry :: ((a, b, ...) -> c) -> a -> b -> ... -> c
function curry(fn) {
  const arity = fn.length;

  return function $curry(...args) {
    if (args.length < arity) {
      return $curry.bind(null, ...args);
    }

    return fn.call(null, ...args);
  };
}

either

// either :: (a -> c) -> (b -> c) -> Either a b -> c
const either = curry((f, g, e) => {
  if (e.isLeft) {
    return f(e.$value);
  }

  return g(e.$value);
});

identity

// identity :: x -> x
const identity = x => x;

inspect

// inspect :: a -> String
const inspect = (x) => {
  if (x && typeof x.inspect === 'function') {
    return x.inspect();
  }

  function inspectFn(f) {
    return f.name ? f.name : f.toString();
  }

  function inspectTerm(t) {
    switch (typeof t) {
      case 'string':
        return `'${t}'`;
      case 'object': {
        const ts = Object.keys(t).map(k => [k, inspect(t[k])]);
        return `{${ts.map(kv => kv.join(': ')).join(', ')}}`;
      }
      default:
        return String(t);
    }
  }

  function inspectArgs(args) {
    return Array.isArray(args) ? `[${args.map(inspect).join(', ')}]` : inspectTerm(args);
  }

  return (typeof x === 'function') ? inspectFn(x) : inspectArgs(x);
};

left

// left :: a -> Either a b
const left = a => new Left(a);

liftA2

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

liftA3

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

maybe

// maybe :: b -> (a -> b) -> Maybe a -> b
const maybe = curry((v, f, m) => {
  if (m.isNothing) {
    return v;
  }

  return f(m.$value);
});

nothing

// nothing :: Maybe a
const nothing = Maybe.of(null);

reject

// reject :: a -> Task a b
const reject = a => Task.rejected(a);