UNPKG

funcprolib

Version:

Functional Programming Library

189 lines (158 loc) 6.07 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: main.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: main.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>import { isError, isFunction, isNull, isUndefined } from "lodash/fp"; import eitherDefinition from "./either"; import maybeDefinition from "./maybe"; export function createMonad(monadDefinition) { return function(input) { // @note Handle different Monad types here ? E.g Either(Maybe()) if (input &amp;&amp; input.isMonad) { return input; } if (isFunction(input)) { return (a) => createMonad(monadDefinition)(a).map(input); } const newMonad = (isError(input) || isNull(input) || Number.isNaN(input) || isUndefined(input)) ? monadDefinition.createErroneousMonad(input) : monadDefinition.createSuccessfulMonad(input); newMonad.isMonad = true; newMonad.toString = () => 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 (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&lt;Function>} fns - Functions to apply on the new monad * @return {Object} A new Monad on which all given functions will * have been called **/ export function flow(monadDefinition) { return function(...fns) { const applier = (input) => fns.reduce( (prev, curr) => prev.map(curr), createMonad(monadDefinition)(input) ); applier.chain = (errorFn) => (input) => applier(input).chain(errorFn); return applier; }; } /** * Debug version of flow * @node Merge with regular flow * @param {Object} monadDefinition - Monad definition * @param {Array&lt;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(...fns) { let functionCall = 0; const applier = (input) => fns.reduce( function(prev, curr) { const debug = "FuncProLib Debug - "; const temp = prev.map(curr); if (prev.chain()) { 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 = (errorFn) => (input) => applier(input).chain(errorFn); return applier; }; }; // @note Merge into one export const when JSLint accepts it (someday ?) const createEither = createMonad(eitherDefinition); const eitherFlow = flow(eitherDefinition); eitherFlow.debug = flow.debug(eitherDefinition); const createMaybe = createMonad(maybeDefinition); const maybeFlow = flow(maybeDefinition); maybeFlow.debug = flow.debug(maybeDefinition); export { createEither, eitherFlow, createMaybe, maybeFlow }; </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#flow">flow</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Nov 29 2016 08:01:47 GMT+0100 (CET) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>