Last active
March 8, 2017 13:08
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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