UNPKG

funcprolib

Version:

Functional Programming Library

164 lines (145 loc) 5.99 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.maybeFlow = exports.createMaybe = exports.eitherFlow = exports.createEither = undefined; exports.createMonad = createMonad; exports.flow = flow; var _fp = require("lodash/fp"); var _either = require("./either"); var _either2 = _interopRequireDefault(_either); var _maybe = require("./maybe"); var _maybe2 = _interopRequireDefault(_maybe); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function createMonad(monadDefinition) { return function (input) { // @note Handle different Monad types here ? E.g Either(Maybe()) if (input && input.isMonad) { return input; } if ((0, _fp.isFunction)(input)) { return function (a) { return createMonad(monadDefinition)(a).map(input); }; } var newMonad = (0, _fp.isError)(input) || (0, _fp.isNull)(input) || Number.isNaN(input) || (0, _fp.isUndefined)(input) ? monadDefinition.createErroneousMonad(input) : monadDefinition.createSuccessfulMonad(input); newMonad.isMonad = true; newMonad.toString = function () { return monadDefinition.toString(newMonad); }; /** * Apply a function on a monad value, but only if the monad is in an ok * state * @param {Function} fn - Function to apply * @return {Object} If everything went right, a new monad with the * result of calling given function with the monad value, or the same * monad, untouched **/ newMonad.map = function (fn) { try { if (monadDefinition.isInErrorState(newMonad)) { return newMonad; } return createMonad(monadDefinition)(fn(monadDefinition.getSuccessfulValue(newMonad))); } catch (err) { return createMonad(monadDefinition)(err); } }; /** * Apply a function on a monad erroneous value, or just return the * monad right value * @node Should be improved to apply given function on right value too * @param {Function} fn - Function to apply * @return {Object} If everything went right the monad value, or the * result of calling the function with the monad's erroneous value **/ newMonad.chain = function (input) { if (monadDefinition.isInErrorState(newMonad)) { if ((0, _fp.isFunction)(input)) { return input(monadDefinition.getErroneousValue(newMonad)); } return input; } // @note According to fantasyland specs, we should apply input on // the monad value, even if it's not in an erroneous state return monadDefinition.getSuccessfulValue(newMonad); }; return newMonad; }; } /** * Create a monad out of given input and map any number of functions * on it * @param {Object} monadDefinition - Monad definition * @param {Array<Function>} fns - Functions to apply on the new monad * @return {Object} A new Monad on which all given functions will * have been called **/ function flow(monadDefinition) { return function () { for (var _len = arguments.length, fns = Array(_len), _key = 0; _key < _len; _key++) { fns[_key] = arguments[_key]; } var applier = function applier(input) { return fns.reduce(function (prev, curr) { return prev.map(curr); }, createMonad(monadDefinition)(input)); }; applier.chain = function (errorFn) { return function (input) { return applier(input).chain(errorFn); }; }; return applier; }; } /** * Debug version of flow * @node Merge with regular flow * @param {Object} monadDefinition - Monad definition * @param {Array<Function>} fns - Functions to apply on the new monad * @return {Object} A new Monad on which all given functions will * have been called **/ flow.debug = function (monadDefinition) { return function () { for (var _len2 = arguments.length, fns = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { fns[_key2] = arguments[_key2]; } var functionCall = 0; var applier = function applier(input) { return fns.reduce(function (prev, curr) { var debug = "FuncProLib Debug - "; var temp = prev.map(curr); if (monadDefinition.isInErrorState(prev)) { console.log(debug + "Monad is in an erroneous state. Bypassing ", curr.toString().split("\n")[0]); } else { functionCall = functionCall + 1; console.log(debug + "Call #" + functionCall); console.log(debug + "Current value=" + prev.toString()); console.log(debug + "Next function=" + curr); console.log(debug + "New value=" + temp.toString()); } return temp; }, createMonad(monadDefinition)(input)); }; applier.chain = function (errorFn) { return function (input) { return applier(input).chain(errorFn); }; }; return applier; }; }; // @note Merge into one export const when JSLint accepts it (someday ?) var createEither = createMonad(_either2.default); var eitherFlow = flow(_either2.default); eitherFlow.debug = flow.debug(_either2.default); var createMaybe = createMonad(_maybe2.default); var maybeFlow = flow(_maybe2.default); maybeFlow.debug = flow.debug(_maybe2.default); exports.createEither = createEither; exports.eitherFlow = eitherFlow; exports.createMaybe = createMaybe; exports.maybeFlow = maybeFlow; //# sourceMappingURL=main.js.map