crocks
Version:
A collection of well known Algebraic Datatypes for your utter enjoyment.
143 lines (106 loc) • 3.71 kB
JavaScript
/** @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