UNPKG

crocks

Version:

A collection of well known Algebraic Datatypes for your utter enjoyment.

144 lines (112 loc) 3.19 kB
/** @license ISC License (c) copyright 2017 original and current authors */ /** @author Ian Hofmann-Hicks (evil) */ var isApply = require('./isApply') var isArray = require('./isArray') var isEmpty = require('./isEmpty') var isFunction = require('./isFunction') var isSameType = require('./isSameType') var isSemigroup = require('./isSemigroup') var apOrFunc = require('./apOrFunc') var identity = function (x) { return x; } var concat = function (x) { return function (m) { return x.concat(m); }; } function runTraverse(name, fn) { return function(acc, x) { var m = fn(x) if(!((isApply(acc) || isArray(acc)) && isSameType(acc, m))) { throw new TypeError(("Array." + name + ": Must wrap Applys of the same type")) } if(isArray(m)) { return ap(acc, map(function (v) { return concat([ v ]); }, m)) } return m .map(function (v) { return concat([ v ]); }) .ap(acc) } } var allFuncs = function (xs) { return xs.reduce(function (b, i) { return b && isFunction(i); }, true); } var map = function (f, m) { return m.map(function (x) { return f(x); }); } function ap(x, m) { if(!(m.length && allFuncs(m))) { throw new TypeError('Array.ap: Second Array must all be functions') } return m.reduce(function (acc, f) { return acc.concat(map(f, x)); }, []) } function chain(f, m) { return m.reduce(function(y, x) { var n = f(x) if(!isArray(n)) { throw new TypeError('Array.chain: Function must return an Array') } return y.concat(n) }, []) } function sequence(f, m) { var fn = apOrFunc(f) return m.reduceRight(runTraverse('sequence', identity), fn([])) } function traverse(f, fn, m) { var af = apOrFunc(f) return m.reduceRight(runTraverse('traverse', fn), af([])) } function fold(m) { if(isEmpty(m)) { throw new TypeError( 'Array.fold: Non-empty Array of Semigroups required' ) } var head = m[0] if(!isSemigroup(head)) { throw new TypeError('Array.fold: Must contain Semigroups of the same type') } return m.reduce(function(x, y) { if(!isSameType(x, y)) { throw new TypeError('Array.fold: Must contain Semigroups of the same type') } return x.concat(y) }) } function foldMap(fn, m) { if(isEmpty(m)) { throw new TypeError( 'Array.foldMap: Non-empty Array required' ) } var head = fn(m[0]) if(!isSemigroup(head)) { throw new TypeError( 'Array.foldMap: Provided function must return Semigroups of the same type' ) } return m.length === 1 ? head : m.slice(1).reduce(function(semi, x) { var val = fn(x) if(!(isSameType(semi, val) && isSemigroup(val))) { throw new TypeError( 'Array.foldMap: Provided function must return Semigroups of the same type' ) } return semi.concat(val) }, head) } function set(indx, val, m) { var arr = m.slice() arr[indx] = val return arr } function unset(indx, m) { return m.slice(0, indx) .concat(m.slice(indx + 1)) } module.exports = { ap: ap, chain: chain, fold: fold, foldMap: foldMap, map: map, sequence: sequence, set: set, traverse: traverse, unset: unset }