UNPKG

crocks

Version:

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

229 lines (177 loc) 5.75 kB
/** @license ISC License (c) copyright 2016 original and current authors */ /** @author Ian Hofmann-Hicks (evil) */ var VERSION = 4 var _equals = require('./equals') var _implements = require('./implements') var _inspect = require('./inspect') var type = require('./types').type('Pair') var _type = require('./types').typeFn(type(), VERSION) var fl = require('./flNames') var isApplicative = require('./isApplicative') var isApply = require('./isApply') var isArray = require('./isArray') var isFunction = require('./isFunction') var isSameType = require('./isSameType') var isSemigroup = require('./isSemigroup') function Pair(l, r) { var obj; if(arguments.length < 2) { throw new TypeError('Pair: Must provide a first and second value') } var fst = function () { return l; } var snd = function () { return r; } var inspect = function () { return ("Pair(" + (_inspect(l)) + "," + (_inspect(r)) + " )"); } var toArray = function () { return [ l, r ]; } function merge(fn) { if(!isFunction(fn)) { throw new TypeError('Pair.merge: Binary function required') } return fn(fst(), snd()) } function equals(m) { return isSameType(Pair, m) && _equals(m.fst(), fst()) && _equals(m.snd(), snd()) } function concat(method) { return function(m) { if(!isSameType(Pair, m)) { throw new TypeError(("Pair." + method + ": Pair required")) } var lf = fst() var ls = snd() var rf = m.fst() var rs = m.snd() if(!(isSemigroup(lf) && isSemigroup(ls))) { throw new TypeError(("Pair." + method + ": Both Pairs must contain Semigroups of the same type")) } if(!(isSameType(lf, rf) && isSameType(ls, rs))) { throw new TypeError(("Pair." + method + ": Both Pairs must contain Semigroups of the same type")) } return Pair( lf.concat(rf), ls.concat(rs) ) } } function swap(f, g) { if(!isFunction(f) || !isFunction(g)) { throw new TypeError('Pair.swap: Requires both left and right functions') } return Pair(g(r), f(l)) } function map(method) { return function(fn) { if(!isFunction(fn)) { throw new TypeError(("Pair." + method + ": Function required")) } return Pair(l, fn(r)) } } function bimap(method) { return function(f, g) { if(!isFunction(f) || !isFunction(g)) { throw new TypeError(("Pair." + method + ": Function required for both arguments")) } return Pair(f(l), g(r)) } } function ap(m) { if(!isSameType(Pair, m)) { throw new TypeError('Pair.ap: Pair required') } var fn = snd() if(!isFunction(fn)) { throw new TypeError('Pair.ap: Function required for second value') } var l = fst() var r = m.fst() if(!(isSemigroup(l) && isSameType(l, r))) { throw new TypeError('Pair.ap: Semigroups of the same type is required for first values') } return Pair(l.concat(r), fn(m.snd())) } function chain(method) { return function(fn) { var l = fst() if(!isFunction(fn)) { throw new TypeError(("Pair." + method + ": Function required")) } if(!isSemigroup(l)) { throw new TypeError(("Pair." + method + ": Semigroups of the same type required for first values")) } var m = fn(snd()) if(!isSameType(Pair, m)) { throw new TypeError(("Pair." + method + ": Function must return a Pair")) } var r = m.fst() if(!isSameType(l, r)) { throw new TypeError(("Pair." + method + ": Semigroups of the same type required for first values")) } return Pair( l.concat(r), m.snd() ) } } function sequence(f) { if(!(isApplicative(f) || isFunction(f))) { throw new TypeError( 'Pair.sequence: Applicative TypeRep or Apply returning function required' ) } if(!(isApply(r) || isArray(r))) { throw new TypeError( 'Pair.sequence: Must wrap an Apply in the second' ) } return r.map(function (v) { return Pair(l, v); }) } function traverse(f, fn) { if(!(isApplicative(f) || isFunction(f))) { throw new TypeError( 'Pair.traverse: Applicative TypeRep or Apply returning function required for first argument' ) } if(!isFunction(fn)) { throw new TypeError( 'Pair.traverse: Apply returning function required for second argument' ) } var m = fn(r) if(!(isApply(m) || isArray(m))) { throw new TypeError( 'Pair.traverse: Both functions must return an Apply of the same type' ) } return m.map(function (v) { return Pair(l, v); }) } function extend(method) { return function(fn) { if(!isFunction(fn)) { throw new TypeError(("Pair." + method + ": Function required")) } return Pair(l, fn(Pair(l, r))) } } return ( obj = { inspect: inspect, toString: inspect, fst: fst, snd: snd, toArray: toArray, type: type, merge: merge, equals: equals, swap: swap, ap: ap, sequence: sequence, traverse: traverse, concat: concat('concat'), map: map('map'), bimap: bimap('bimap'), chain: chain('chain'), extend: extend('extend') }, obj[fl.equals] = equals, obj[fl.concat] = concat(fl.concat), obj[fl.map] = map(fl.map), obj[fl.bimap] = bimap(fl.bimap), obj[fl.chain] = chain(fl.chain), obj[fl.extend] = extend(fl.extend), obj['@@type'] = _type, obj.constructor = Pair, obj ) } Pair.type = type Pair['@@type'] = _type Pair['@@implements'] = _implements( [ 'ap', 'bimap', 'chain', 'concat', 'extend', 'equals', 'map', 'traverse' ] ) module.exports = Pair