Skip to content

Instantly share code, notes, and snippets.

@ivenmarquardt
Last active March 8, 2017 13:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ivenmarquardt/64fd59dd5387c855cb8c28d85453cf90 to your computer and use it in GitHub Desktop.
Save ivenmarquardt/64fd59dd5387c855cb8c28d85453cf90 to your computer and use it in GitHub Desktop.
Dynamic Javascript type checker for curried functions (functional programming, currying, partial application, debug, debugging)
const reflectf = (...preds) => (...arities) => (f, tag = f.name) => (...args) => {
if (args.length !== arities[0]) {
throw new TypeError(`${tag} expects an ${arities[0]}-ary lambda (${args.length}-ary given)`);
}
args.forEach((arg, i) => preds[i](arg));
const r = f(...args);
if (args.length === arities.length) return (preds[1](r), r);
if (typeof r !== "function") {
throw new TypeError(`${tag} must return a lambda (${typeof r} given)`);
}
return reflectf(...preds.slice(args.length)) (...arities.slice(args.length)) (r, tag);
}
const orLog = type => template => x => log(print(template) (type, typeof x));
const orRaise = type => template => x => raise(TypeError) (print(template) (type, typeof x));
const validate = type => f => template => guard(f(type) (template)) (isNotTypeOf(type));
const invalidArgOf = tag => tag + " expects ${0} as argument (${1} given)";
const invalidRVOf = tag => tag + " must return ${0} (${1} given)";
const log = (...args) =>console.log(...args);
const guard = f => pred => x => pred(x) ? f(x) : x;
const negf = f => x => !f(x);
const raise = ctor => x => { throw new ctor(x) };
const print = template => (...args) => template.replace(/\$\{(\d+)}/g, (_, i) => args[i]);
const instanceOf = ctor => x => x instanceof ctor;
const isNotTypeOf = type => x => typeof x !== type;
const isTypeOf = type => x => typeof x === type;
const typeOf = x => typeof x;
const K = x => _ => x;
const sum = x => y => z => x + y + z;
const sum_ = reflectf(
validate("number") (orLog) (invalidArgOf("sum")),
validate("number") (orLog) (invalidArgOf("sum")),
validate("number") (orLog) (invalidArgOf("sum")),
K(false) // skip check of return value
) (1, 1, 1) (sum);
console.log(sum_(1) (2) (3)); // 6
console.log(sum_(1) ("2") (3)); // "123" => logs "sum expects number as argument (string given)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment