UNPKG

monad-ts

Version:

Monad-ts is a small library implements some of key monads and way to chain them in a pipe (flow) in JavaScript and TypeScript. Angular 2+ compatible.

334 lines (322 loc) 19.6 kB
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <base data-ice="baseUrl"> <title data-ice="title">API Document</title> <link type="text/css" rel="stylesheet" href="css/style.css"> <link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css"> <script src="script/prettify/prettify.js"></script> <script src="script/manual.js"></script> </head> <body class="layout-container" data-ice="rootContainer"> <header> <a href="./">Home</a> <a href="identifiers.html">Reference</a> <a href="source.html">Source</a> <a data-ice="repoURL" href="https://github.com/sash-ua/monad-ts" class="repo-url-github">Repository</a> <div class="search-box"> <span> <img src="./image/search.png"> <span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span> </span> <ul class="search-result"></ul> </div> </header> <nav class="navigation" data-ice="nav"><div> <ul> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/asyncFlow.js~AsyncFlow.html">AsyncFlow</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/either.js~Either.html">Either</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/error.js~ErrorM.html">ErrorM</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/flow.js~Flow.html">Flow</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/identity.js~Identity.html">Identity</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/list.js~List.html">List</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/maybe.js~Maybe.html">Maybe</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/monad.js~Monad.html">Monad</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/state.js~State.html">State</a></span></span></li> <li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">interfaces</div><span data-ice="kind" class="kind-interface">I</span><span data-ice="name"><span><a href="class/src/interfaces/m.js~M.html">M</a></span></span></li> <li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">services</div><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-cast">cast</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-clone">clone</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-debounceTime">debounceTime</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-equality">equality</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-hash">hash</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-function">F</span><span data-ice="name"><span><a href="function/index.html#static-function-wait">wait</a></span></span></li> <li data-ice="doc"><div data-ice="dirPath" class="nav-dir-path">types</div><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-D&lt;T&gt;">D&lt;T&gt;</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-MF&lt;T,U&gt;">MF&lt;T,U&gt;</a></span></span></li> <li data-ice="doc"><span data-ice="kind" class="kind-typedef">T</span><span data-ice="name"><span><a href="typedef/index.html#static-typedef-Pr&lt;U&gt;">Pr&lt;U&gt;</a></span></span></li> </ul> </div> </nav> <div class="content" data-ice="content"><div data-ice="index" class="github-markdown"><p><a href="https://travis-ci.org/sash-ua/monad-ts"><img src="https://travis-ci.org/sash-ua/monad-ts.svg?branch=master" alt="Build Status"></a> <a href="https://github.com/sash-ua/monad-ts"><img src="https://img.shields.io/npm/dw/localeval.svg" alt="npm"></a> <a href="https://github.com/sash-ua/monad-ts"><img src="https://img.shields.io/gemnasium/mathiasbynens/he.svg" alt="Gemnasium"></a> <a href="https://github.com/sash-ua/monad-ts"><img src="https://img.shields.io/hexpm/l/plug.svg" alt="Hex.pm"></a></p> <h1 id="monad-ts">Monad-ts</h1> <p>Monad-ts is a small library implements some of key monads and way to chain them in a flow (pipe) in JavaScript and Typescript. Angular 2+ compatible</p> <p><a href="https://github.com/sash-ua/gen_drift_monad-ts_a4/">Example app 1</a>.</p> <p><a href="https://github.com/sash-ua/todos-next">Example app 2 with monad transformers</a>.</p> <h2 id="content">Content</h2> <ul> <li><a href="#installation">Installation</a></li> <li><a href="#tests">Tests</a></li> </ul> <p><strong>Introduction</strong></p> <ul> <li><a href="#intro">Intro</a></li> <li><a href="#setup">Setup</a></li> <li><a href="https://sash-ua.github.io/monad-ts/identifiers.html">API</a></li> </ul> <p><strong>All monads</strong></p> <ul> <li><a href="#either">Either</a></li> <li><a href="#errorm">ErrorM</a></li> <li><a href="#identity">Identity</a></li> <li><a href="#maybe">Maybe</a></li> <li><a href="#list">List</a></li> <li><a href="#state">State</a></li> </ul> <p><strong>Additional tools (class and functions)</strong></p> <ul> <li><a href="#asyncflow">AsyncFlow</a></li> <li><a href="#flow">Flow</a></li> <li><a href="#cast">cast</a></li> <li><a href="#clone">clone</a></li> <li><a href="#debouncetime">debounceTime</a></li> <li><a href="#equality">equality</a></li> <li><a href="#hash">hash</a></li> <li><a href="#wait">wait</a></li> </ul> <p><strong>Examples</strong></p> <ul> <li><a href="https://github.com/sash-ua/monad-ts/tree/master/test">Monad examples</a></li> <li><a href="https://github.com/sash-ua/todos-next/blob/master/src/app/services/monad.service/monad.service.ts">Monad transformer examples</a></li> <li><a href="https://github.com/sash-ua/gen_drift_monad-ts_a4">App 1</a></li> <li><a href="https://github.com/sash-ua/todos-next">App 2 with Monad transformers</a></li> </ul> <h2 id="installation">Installation</h2> <p>In library used ES5 (Array.map, Array.reduce, Array.some, Array.isArray, Object.getOwnPropertyNames), ES6 (Map, Array.from, Object.assign, Object.keys, Object.is) methods. It&apos;s strongly recommended to always use ES5-shim and ES6-shim or alternatives.</p> <pre><code><code class="source-code prettyprint">npm install monad-ts</code> </code></pre><p>or</p> <pre><code><code class="source-code prettyprint"> yarn add monad-ts</code> </code></pre><h2 id="tests">Tests</h2> <p>Clone the repo, <code>npm install</code> or <code>yarn</code> and run tests.</p> <pre><code><code class="source-code prettyprint">npm run test</code> </code></pre><p>or</p> <pre><code><code class="source-code prettyprint"> yarn test</code> </code></pre><h2 id="intro">Intro</h2> <p>One of the main ideas of functional programming is to use pure functions as much as possible. But pure functions don&apos;t do any kind of side-effects. At the same time the majority of programs should operate with side-effects in process. Monads allow us to do all the side-effecting computations using pure functions effectively.</p> <p><strong>NB</strong> This monads implementation aren&apos;t exact copy of Haskell monads. My goal was to reach results comparable with the using of like monads from Haskell in JS.</p> <p><strong>NB</strong> For catching Errors, produced within monads you should use monad ErrorM.</p> <h2 id="setup">Setup</h2> <p><strong>1.</strong> <strong>SystemJS</strong> Configure <code>systemjs.config.js</code> to register the module.</p> <pre><code><code class="source-code prettyprint">SystemJS.config({ map:{ ... &apos;monad-ts&apos;: &apos;node_modules/monad-ts/lib/monad_ts.umd.js&apos; ... } })</code> </code></pre><p><strong>2.</strong> <strong>WebPack</strong> No special configuration.</p> <p>Example:</p> <pre><code><code class="source-code prettyprint">import {Flow, List} from &quot;monad-ts&quot; const list = new List(); const e: number = 50; let r : number; let t : number[]; console.log(t); // undefined console.log(r); // undefined const z = new Flow(5) .bind((v: number): any =&gt; v+1) .let((v: number): any =&gt; new Flow(v).bind((v: number) =&gt; r = v+e)) .bind((v: number): any =&gt; cast(list.bind((v: number) =&gt; [v-1, v, v+1], [-v, v ]), 1)) .let((v: number)=&gt; new Flow(v).bind((v: number[]) =&gt; t = v, cast(list.bind((v: number)=&gt;[v, -v], [v]), 2))) .subscribe(); console.log(r); // 56 console.log(t); // [ -7, 7, -6, 6, -5, 5, 5, -5, 6, -6, 7, -7 ] console.log(z); // [ -7, -6, -5, 5, 6, 7 ]</code> </code></pre><p><a href="#monad-ts">UP</a></p> <h2 id="monads">Monads</h2> <h4 id="either">Either</h4> <p>It represents computation with two possibilities, <code>right</code> and <code>left</code>. Attached by bind method dispatcher function decided which of them apply to underlying value.</p> <p>Example:</p> <pre><code><code class="source-code prettyprint">const uVal = 10; // underlying value const right = (x: number) =&gt; x+1; // if cond(v) return true, than executed const left = (y: string) =&gt; y + &apos; - isn\&apos;t string&apos;; // if cond(v) return false, than executed const cond = (v:any) =&gt; typeof v === &apos;string&apos;; // dispatcher function - cond(v) const e = new Either(right, left).bind(cond , uVal); // &apos;10 - isn&apos;t string&apos;</code> </code></pre> <h4 id="errorm">ErrorM</h4> <p>It similar to the Identity but it can also represent the error. Error monad returns value transformed by given function. If Error monad gets Error in given values it produce Error. If after application of given transformation function monad get Error monad produce Error.</p> <p>Examples:</p> <pre><code><code class="source-code prettyprint">const e = new ErrorM(); e.bind((v: number) =&gt; e.bind((v1: number)=&gt;v+v1, 1), 1/0); // Error</code> </code></pre><h4 id="identity">Identity</h4> <p>It returns underlying value transformed by given function. We can add underlying value in constructor or in bind method.</p> <p>Examples:</p> <pre><code><code class="source-code prettyprint">const i = new Identity(3); // Identity({v: 3}) i.bind((v:number) =&gt; v); // 3</code> </code></pre><pre><code><code class="source-code prettyprint">const i = new Identity(); i.bind((v:number) =&gt; v, 3); // 3 </code> </code></pre><h4 id="maybe">Maybe</h4> <p>It similar to the Identity but it can also represent the absence of any value. Monad Maybe returns value transformed by given function. If Maybe monad gets null or undefined in given values it produce null. If after application of given transformation function monad get null or undefined monad produce null.</p> <p>Examples:</p> <pre><code><code class="source-code prettyprint">const maybe = new Maybe(); type G = { url: string; getUrl: () =&gt; any; }; const z: G = { url: &apos;http://...&apos;, getUrl: function (){ return this.url; } }; maybe.bind(r =&gt; r.getUrl(), z); // http://...</code> </code></pre><h4 id="list">List</h4> <p>The List monad represents a computed list of values. It takes in an input value of type A, and produce a bunch of output values of type B, collected in one container (the array).</p> <p>It get array and return array, to cast array dimension according to entered array we can use function <a href="#cast">cast</a>;</p> <p>Examples:</p> <pre><code><code class="source-code prettyprint">const list = new List(); const x = [10, 2]; // Entered array z = cast(list.bind((v: number) =&gt;list.bind((v: number) =&gt; [-v, v], [v-1, v, v+1]), x), 2); // [ -9, 9, -10, 10, -11, 11, -1, 1, -2, 2, -3, 3 ]</code> </code></pre><h4 id="state">State</h4> <p>The State monad interact with local and global state variables to transform them. After initializing an instance of State monad we can not add new keys to the state object. It take object.</p> <p>The instance of the State monad can be initialized in two ways.</p> <ol> <li><p>While the instance create - in constructor (Ex.1).</p> </li> <li><p>After instance created - use <code>bind()</code> method (Ex.2). The function <code>x =&gt; x</code> in <code>st.bind(x =&gt; x, initState)</code> is for backward compatibility with previous versions, it&apos;s unused in the method. Delayed initialization can be useful in some cases.</p> </li> </ol> <p>Example 1:</p> <pre><code><code class="source-code prettyprint">type R = { data: number; children: any[]; arr: number[]; }; const initState: R = { data: 1, children: [{ data: 2, parent: &apos;null&apos; }], arr:[1,2,3] }; const st = new State(initState); console.log(st.get()); // return initState object st.put((v: R) =&gt; { v.data = 10; v.arr = list.bind((x:number) =&gt; x+f, v.arr); return v; }); console.log(st.get()); // { data: 10, children: [ Object({ data: 2, parent: &apos;null&apos; }) ], arr: [ 2.25, 3.25, 4.25 ] }</code> </code></pre><p>Example 2:</p> <pre><code><code class="source-code prettyprint">type R = { data: number; children: any[]; arr: number[]; }; const initState: R = { data: 1, children: [{ data: 2, parent: null }], arr:[1,2,3] }; const st = new State(); console.log(st.get()); // State -&gt; undefined st.bind(x =&gt; x, initState); st.put((v: R) =&gt; { v.data = 10; v.arr = list.bind((x:number) =&gt; x+f, v.arr); return v; }); console.log(st.get()); // State -&gt; { data: 10, children: [ Object({ data: 2, parent: null }) ], arr: [ 2.25, 3.25, 4.25 ] }</code> </code></pre><p><a href="#monad-ts">UP</a></p> <h2 id="additional-utilities-class-and-functions-">Additional utilities (class and functions)</h2> <h4 id="asyncflow">AsyncFlow</h4> <p>For composing monads in an async flow (pipe), based on Promise. Class instance creation <code>new AsyncFlow(initV, encapsulate?)</code>. Initial value (initV) encapsulated in the class instance by default. If set encapsulate = false, then initial value wouldn&apos;t be encapsulated and we will be able to change inner state of the class instance by changing <code>initV</code>.</p> <p><strong>NB</strong> Initial value should be statically analyzable.</p> <pre><code><code class="source-code prettyprint">new AsyncFlow(5) .bind((v) =&gt; v) .then((v) =&gt; v) .then((v) =&gt; cast(list.bind((v:number) =&gt; [v-1, v, v+1], [v]), 1)) .then(v=&gt; wait(v,100)) .then((v)=&gt; { console.log(v); // v = [4,5,6], emitted after 100 ms });</code> </code></pre><h4 id="flow">Flow</h4> <p>For composing monads in a flow (pipe). Class instance creation is identical to AsyncFlow.</p> <pre><code><code class="source-code prettyprint">const e: number = 50; let r : number; let t : number[]; const z = new Flow(5) .bind((v: number): any =&gt; v+1) .let((v: number): any =&gt; new Flow(v).bind((v: number) =&gt; r = v+e)) .bind((v: number): any =&gt; cast(list.bind((v: number) =&gt; [v-1, v, v+1], [-v, v ]), 1)) .let((v: number)=&gt; new Flow(v).bind((v: number[]) =&gt; t = v, cast(list.bind((v: number)=&gt;[v, -v], [v]), 2))) .subscribe(); console.log(r); // 56 console.log(t); // [ -7, 7, -6, 6, -5, 5, 5, -5, 6, -6, 7, -7 ] console.log(z); // [ -7, -6, -5, 5, 6, 7 ]</code> </code></pre><h4 id="cast">cast</h4> <p>Function to decreasing the dimension of an array by factor <code>n</code>. It takes array and factor.</p> <pre><code><code class="source-code prettyprint">console.log(cast([10, [11], [12]], 0)); // [10, [11], [12]] console.log(cast([10, [[11, [2]], 3], [12]], 2)); // [ 10, 11, [ 2 ], 3, 12 ]</code> </code></pre><h4 id="clone">clone</h4> <p>Function to clone objects (including Map). It takes objects, arrays and primitives.</p> <pre><code><code class="source-code prettyprint">const x = {x:1}; const z = clone(x); z.x = 10; console.log(z); // {x:10} console.log(x); // {x:1}</code> </code></pre><h4 id="debouncetime">debounceTime</h4> <p>Execute a function given a delay time. <code>debounceTime(func, d, i?)</code>, <code>func</code> - invoked function, <code>d</code> - a delay time, <code>i</code> - delay before <code>func</code> execution, by default is absent.</p> <h4 id="equality">equality</h4> <p>It checks equality of given arguments, arguments must be statically analyzable, therefore there are some constraints, look at <strong><a href="https://sash-ua.github.io/monad-ts/function/index.html#static-function-equality">examples</a></strong> to find them.</p> <pre><code><code class="source-code prettyprint">// true equality( {x1: 0, x: [1, {c: [22, {j:21, g: &apos;ert&apos;}, 23]}, NaN, Infinity, null, undefined], t: [null, 0]}, {x1: 0, x: [1, {c: [22, {j:21, g: &apos;ert&apos;}, 23]}, NaN, Infinity, null, undefined], t: [null, 0]} )</code> </code></pre><h4 id="hash">hash</h4> <p>It calculates a hash (32 bit).</p> <pre><code><code class="source-code prettyprint">let g = hash(&apos;test &quot;#^test &quot;#^test &quot;#^testRrr G!@#$%^&amp;*()__+&lt;&gt;?ZXCV&quot;:A&apos;); // g = 2692353561</code> </code></pre><h4 id="wait">wait</h4> <p>Function to convert timeout in a Promise, resolved when specified amount of time passes. It take value (v) end emit Promise after t timeout with value (v). <code>wait(v, t)</code> It produce a promise rejection handler on an Error occur.</p> <pre><code><code class="source-code prettyprint">const s = wait(1, 300).then((v: number)=&gt;{ console.log(v); // v = 1, emitted after 300 ms })</code> </code></pre><p><a href="#monad-ts">UP</a></p> <h2 id="license">License</h2> <p>Monad_ts is copyright (c) 2017 - present Alex Tranchenko tranchenkoa@gmail.com .</p> <p>Monad_ts is free software, licensed under the Apache License, Version 2.0. See the file LICENSE.md in this distribution for more details.</p> </div> </div> <footer class="footer"> Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(0.5.2)</span><img src="./image/esdoc-logo-mini-black.png"></a> </footer> <script src="script/search_index.js"></script> <script src="script/search.js"></script> <script src="script/pretty-print.js"></script> <script src="script/inherited-summary.js"></script> <script src="script/test-summary.js"></script> <script src="script/inner-link.js"></script> <script src="script/patch-for-local.js"></script> </body> </html>