UNPKG

crocks

Version:

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

143 lines (106 loc) 3.71 kB
/** @license ISC License (c) copyright 2017 original and current authors */ /** @author Ian Hofmann-Hicks (evil) */ var VERSION = 1 var _implements = require('../core/implements') var _inspect = require('../core/inspect') var _type = require('../core/types').type('Reader')() var _typeString = require('../core/types').typeFn(_type, VERSION) var fl = require('../core/flNames') var curry = require('../core/curry') var isFunction = require('../core/isFunction') var isMonad = require('../core/isMonad') var isSameType = require('../core/isSameType') function _ReaderT(Monad) { if(!isMonad(Monad)) { throw new TypeError('ReaderT: Monad required for construction') } var type = function () { return (_type + "( " + (Monad.type()) + " )"); } var typeString = _typeString + "( " + (Monad['@@type']) + " )" var of = function (x) { return ReaderT(function () { return Monad.of(x); }); } function ask(fn) { if(!arguments.length) { return ReaderT(Monad.of) } if(isFunction(fn)) { return ReaderT(Monad.of).map(fn) } throw new TypeError(((type()) + ".ask: No argument or function required")) } function lift(m) { if(!isSameType(Monad, m)) { throw new TypeError(((type()) + ".lift: " + (Monad.type()) + " instance required")) } return ReaderT(function () { return m; }) } function liftFn(fn, x) { if(!isFunction(fn)) { throw new TypeError(((type()) + ".liftFn: " + (Monad.type()) + " returning function required")) } return ReaderT(function() { var m = fn(x) if(!isSameType(Monad, m)) { throw new TypeError(((type()) + ".liftFn: " + (Monad.type()) + " returning function required")) } return m }) } function ReaderT(wrapped) { var obj; if(!isFunction(wrapped)) { throw new TypeError(((type()) + ": " + (Monad.type()) + " returning function required")) } var inspect = function () { return ("" + (type()) + (_inspect(wrapped))); } function runWith(x) { var result = wrapped(x) if(!isSameType(Monad, result)) { throw new TypeError(((type()) + ": " + (Monad.type()) + " must be returned by wrapped function")) } return result } function map(fn) { if(!isFunction(fn)) { throw new TypeError(((type()) + ".map: Function required")) } return ReaderT(function (e) { return runWith(e).map(fn); }) } function ap(m) { if(!isSameType(ReaderT, m)) { throw new TypeError(((type()) + ".ap: " + (type()) + " required")) } return ReaderT(function (e) { return runWith(e).ap(m.runWith(e)); }) } function chain(fn) { if(!isFunction(fn)) { throw new TypeError(((type()) + ".chain: " + (type()) + " returning function required")) } return ReaderT(function (e) { return runWith(e).chain(function (inner) { var m = fn(inner) if(!isSameType(ReaderT, m)) { throw new TypeError(((type()) + ".chain: Function must return a " + (type()))) } return m.runWith(e) }); } ) } return ( obj = { inspect: inspect, toString: inspect, type: type, runWith: runWith, of: of, map: map, ap: ap, chain: chain }, obj[fl.of] = of, obj[fl.map] = map, obj[fl.chain] = chain, obj['@@type'] = typeString, obj.constructor = ReaderT, obj ) } ReaderT.type = type ReaderT.of = of ReaderT.ask = ask ReaderT.lift = lift ReaderT.liftFn = curry(liftFn) ReaderT[fl.of] = of ReaderT['@@type'] = typeString ReaderT['@@implements'] = _implements( [ 'ap', 'chain', 'map', 'of' ] ) return ReaderT } module.exports = _ReaderT