UNPKG

crocks

Version:

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

142 lines (107 loc) 3.73 kB
/** @license ISC License (c) copyright 2016 original and current authors */ /** @author Ian Hofmann-Hicks (evil) */ var VERSION = 3 var _equals = require('../core/equals') var _implements = require('../core/implements') var _inspect = require('../core/inspect') var _type = require('../core/types').type('Const') var typeFn = require('../core/types').typeFn var fl = require('../core/flNames') var isFunction = require('../core/isFunction') var isMonoid = require('../core/isMonoid') var isSameType = require('../core/isSameType') var isSemigroup = require('../core/isSemigroup') var typeOrName = function (m) { return isFunction(m.type) ? m.type() : m.name; } var constant = function (x) { return function () { return x; }; } var empties = { Array: function () { return []; }, String: function () { return ''; } } var getEmpty = function (T) { return T[fl.empty] || T.empty || empties[T.name]; } var validMonoid = function (T) { return isMonoid(T) || T.name === 'String' || T.name === 'Array'; } function _Const(T) { if(!isFunction(T)) { throw new TypeError('Const: TypeRep required for construction') } var type = constant(_type(typeOrName(T))) var typeString = typeFn('Const', VERSION, typeOrName(T)) function empty(method) { return function() { if(!validMonoid(T)) { throw new TypeError(((type()) + "." + method + ": Must be fixed to a Monoid")) } return Const(getEmpty(T)()) } } function of(method) { return function() { if(!validMonoid(T)) { throw new TypeError(((type()) + "." + method + ": Must be fixed to a Monoid")) } return Const(getEmpty(T)()) } } function Const(value) { var obj; if(!isSameType(T, value)) { throw new TypeError(((type()) + ": " + (typeOrName(T)) + " required")) } var inspect = constant(("" + (type()) + (_inspect(value)))) var valueOf = constant(value) var equals = function (m) { return isSameType(Const, m) && _equals(value, m.valueOf()); } function concat(method) { return function(m) { if(!isSemigroup(value)) { throw new TypeError(((type()) + "." + method + ": Must be fixed to a Semigroup")) } if(!isSameType(Const, m)) { throw new TypeError(((type()) + "." + method + ": " + (type()) + " required")) } return Const(value.concat(m.valueOf())) } } function map(method) { return function(fn) { if(!isFunction(fn)) { throw new TypeError(((type()) + "." + method + ": Function required")) } return Const(value) } } function ap(m) { if(!isSemigroup(value)) { throw new TypeError(((type()) + ".ap: Must be fixed to a Semigroup")) } if(!isSameType(Const, m)) { throw new TypeError(((type()) + ".ap: " + (type()) + " required")) } return Const(value.concat(m.valueOf())) } return ( obj = { inspect: inspect, toString: inspect, valueOf: valueOf, type: type, ap: ap, equals: equals, concat: concat('concat'), empty: empty('empty'), map: map('map'), of: of('of') }, obj[fl.concat] = concat(fl.concat), obj[fl.empty] = empty(fl.empty), obj[fl.equals] = equals, obj[fl.map] = map(fl.map), obj[fl.of] = of(fl.of), obj['@@type'] = typeString, obj.constructor = Const, obj ) } Const.empty = empty('empty') Const.of = of('of') Const.type = type Const[fl.empty] = empty(fl.empty) Const[fl.of] = of(fl.of) Const['@@type'] = typeString Const['@@implements'] = _implements( [ 'ap', 'concat', 'empty', 'equals', 'map', 'of' ] ) return Const } module.exports = _Const