{"id":16628885,"url":"https://github.com/critocrito/dashp","last_synced_at":"2025-03-21T15:31:18.164Z","repository":{"id":26893559,"uuid":"109573921","full_name":"critocrito/dashp","owner":"critocrito","description":"Utilities for monadic promises.","archived":false,"fork":false,"pushed_at":"2023-01-06T01:40:14.000Z","size":1501,"stargazers_count":4,"open_issues_count":15,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-01T07:23:28.672Z","etag":null,"topics":["browser","functional-js","functional-programming","javascript","monadic","nodejs","promises"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/critocrito.png","metadata":{"files":{"readme":"Readme.md","changelog":"Changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-05T11:36:05.000Z","updated_at":"2022-04-16T09:48:50.000Z","dependencies_parsed_at":"2023-01-14T07:45:22.101Z","dependency_job_id":null,"html_url":"https://github.com/critocrito/dashp","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/critocrito%2Fdashp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/critocrito%2Fdashp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/critocrito%2Fdashp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/critocrito%2Fdashp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/critocrito","download_url":"https://codeload.github.com/critocrito/dashp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244822635,"owners_count":20516143,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","functional-js","functional-programming","javascript","monadic","nodejs","promises"],"created_at":"2024-10-12T04:37:56.157Z","updated_at":"2025-03-21T15:31:17.694Z","avatar_url":"https://github.com/critocrito.png","language":"TypeScript","readme":"# DashP\n\nUtilities for monadic promises.\n\n## Synopsis\n\n[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![npm version](https://img.shields.io/npm/v/dashp.svg?style=flat)](https://www.npmjs.com/package/dashp) ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/critocrito/dashp/Build%20Status?style=flat-square) [![Coverage Status](https://coveralls.io/repos/github/critocrito/dashp/badge.svg)](https://coveralls.io/github/critocrito/dashp)\n\nDashP allows to program with\n[Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)\nin a functional style. It offers a collection of higher-order and utility\nfunctions that operate on Promises and are all curried. It feels similar to\n[`lodash/fp`](https://github.com/lodash/lodash/wiki/FP-Guide), but then for\npromises.\n\nIt implements [an (almost) *monadic* interface](#interoperability) for\nPromises, but unlike other [great](https://github.com/briancavalier/creed)\n[libraries](https://github.com/fluture-js/Fluture) it doesn't introduce new\nsemantics. It just forms a small wrapper around the native Promise API. This\nis great for integrating it into any codebase that already uses Promises,\nwithout having to relearn new semantics or changing the structure. It retains\nas well the eager execution semantics of native Promises.\n\nThis library intends to be very lightweight. It has no external dependencies\nand has a size of 3-4K when minified and gzipped.\n\n\n```javascript\nimport {getJson, storeDb} from './async-utils';\nimport {flowP, tapP} from 'dashp';\n\nconst url = \"https://url.horse/api\";\n\nconst apiCall = flowP([getJson, tapP(console.log), storeDb]);\n\nawait apiCall(url);\n```\n\n## Interoperability\n\n\u003ca href=\"http://promises-aplus.github.com/promises-spec\"\u003e\u003cimg width=\"82\" height=\"82\" alt=\"Promises/A+\" src=\"https://promisesaplus.com/assets/logo-small.png\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/rpominov/static-land\"\u003e\u003cimg width=\"131\" height=\"82\" src=\"https://raw.githubusercontent.com/rpominov/static-land/master/logo/logo.png\" /\u003e\u003c/a\u003e\n\nDashP is [compatible with Promises/A+ and ES6 Promises](promises).\nIt also implements [Static Land](https://github.com/rpominov/static-land)\n[`Functor`](https://github.com/rpominov/static-land/blob/master/docs/spec.md#functor),\n[`Bifunctor`](https://github.com/rpominov/static-land/blob/master/docs/spec.md#bifunctor),\n[`Apply`](https://github.com/rpominov/static-land/blob/master/docs/spec.md#apply),\n[`Applicative`](https://github.com/rpominov/static-land/blob/master/docs/spec.md#applicative),\n[`Chain`](https://github.com/rpominov/static-land/blob/master/docs/spec.md#chain)\nand\n[`Monad`](https://github.com/rpominov/static-land/blob/master/docs/spec.md#monad).\n\nAs [Avaq](https://github.com/Avaq) points out in\n[#1](https://github.com/critocrito/dashp/issues/1), Promises in their current\nimplementation can't be real Applicative Functors. If a Promise holds another\nPromise, it automatically assimilates it's value. The `then` interface acts as\n`map` and `flatMap` at the same time. Therefore `dashp` is cheating on the\nprecise semantics of Applicatives.\n\n## Contents\n\n- [Usage](#usage)\n- [API](#api)\n\n## Usage\n\n    npm install --save dashp\n\nEvery function has an alias that appends _P_ to the function name,\ne.g. `flowP` is an alias for `flow` and `collectP3` is an alias for\n`collect3`. This allows for cleaner imports in situations where function names\ncan clash.\n\n```javascript\nimport {map, sum} from \"lodash/fp\";\nimport {mapP} from \"dashp\";\n\nmap(sum, [1, 2, 3]); // Lodash version.\nmapP(sum, [1, 2, 3]); // dashp version.\n```\n\nDashP depends on [`Array.isArray`](JS:Array.isArray). You may need\nto polyfill it if your JavaScript environment doesn't provide it.\n\n## API\n\n\u003cdetails\u003e\u003csummary\u003eCreating new Promises\u003c/summary\u003e\n\n- [`of`: Lift a value into a promise.](#of)\n- [`reject`: Create a rejected promise.](#reject)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eTransforming and combining Promises\u003c/summary\u003e\n\n- [`map`: Map a function over a promise.](#map)\n- [`bimap`: Map either the left or right function over a promise.](#bimap)\n- [`ap`: Apply a function wrapped in a promise to a promisified value.](#ap)\n- [`chain`: Map a function over a promise.](#chain)\n- [`compose`: Compose two functions that return promises.](#compose)\n- [`whenElse`: Branch left if the predicate holds, otherwise branch right.](#whenelse)\n- [`when`: Conditionally call a function if the predicate holds.](#when)\n- [`unlessElse`: Branch left if the predicate doesn't hold, otherwise branch right.](#unlesselse)\n- [`unless`: Conditionally call a function if the predicate doesn't hold.](#unless)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eCollections\u003c/summary\u003e\n\n- [`all`: Resolve all promises in an array.](#all)\n- [`fold`: Reduce a list of values to a single value, using a reduction function.](#fold)\n- [`collect`: Map a function over every element of a list.](#collect)\n- [`collect2`: Map a function over every element of a list, two at a time.](#collect2)\n- [`collect3`: Map a function over every element of a list, three at a time.](#collect3)\n- [`collect4`: Map a function over every element of a list, four at a time.](#collect4)\n- [`collect5`: Map a function over every element of a list, five at a time.](#collect5)\n- [`collect6`: Map a function over every element of a list, six at a time.](#collect6)\n- [`collect7`: Map a function over every element of a list, seven at a time.](#collect7)\n- [`collect8`: Map a function over every element of a list, eight at a time.](#collect8)\n- [`flatmap`: Map a function over every element of a list and concatenate the results.](#flatmap)\n- [`flatmap2`: Map a function over every element of a list and concatenate the results, two at a time.](#flatmap2)\n- [`flatmap3`: Map a function over every element of a list and concatenate the results, three at a time.](#flatmap3)\n- [`flatmap4`: Map a function over every element of a list and concatenate the results, four at a time.](#flatmap4)\n- [`flatmap5`: Map a function over every element of a list and concatenate the results, five at a time.](#flatmap5)\n- [`flatmap6`: Map a function over every element of a list and concatenate the results, six at a time.](#flatmap6)\n- [`flatmap7`: Map a function over every element of a list and concatenate the results, seven at a time.](#flatmap7)\n- [`flatmap8`: Map a function over every element of a list and concatenate the results, eight at a time.](#flatmap8)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eUtility functions\u003c/summary\u003e\n\n- [`isPromise`: Determine whether value is a promise.](#ispromise)\n- [`tap`: Call a function for side effect and return the original value.](#tap)\n- [`tapClone`: Call a function for side effect and return the original value.](#tapclone)\n- [`caught`: Catch an exception on a promise and call a handler.](#caught)\n- [`spread`: Call a variadic function with the value of a promise as it's arguments.](#spread)\n- [`flow`: Compose functions into a chain.](#flow)\n- [`flow2`: Lift a composed function chain over two arguments.](#flow2)\n- [`flow3`: Lift a composed function chain over three arguments.](#flow3)\n- [`flow4`: Lift a composed function chain over four arguments.](#flow4)\n- [`flow5`: Lift a composed function chain over five arguments.](#flow5)\n- [`flow6`: Lift a composed function chain over six arguments.](#flow6)\n- [`flow7`: Lift a composed function chain over seven arguments.](#flow7)\n- [`flow8`: Lift a composed function chain over eight arguments.](#flow8)\n- [`constant`: Create a function that always returns the same value.](#constant)\n- [`lift2`: Lift a binary function over two promises.](#lift2)\n- [`lift3`: Lift a ternary function over three promises.](#lift3)\n- [`lift4`: Lift a quatary function over four promises.](#lift4)\n- [`delay`: Delay the resolution of a promise chain.](#delay)\n- [`retry`: Call an action, and retry it in case it fails.](#retry)\n\n\u003c/details\u003e\n\n### `of`\n\nLift a value into a promise.\n\n```hs\nof :: b -\u003e Promise a b\n```\n\nThis is equivalent to `Promise.resolve`. It returns a promise that resolves to\nthe applied value. This function is compliant with the [Static Land\nApplicative specification][SL:applicative].\n\n```javascript\nimport {of} from \"dashp\";\n\nconst p = of(23);\n\np.then(x =\u003e console.log(`${x} things.`));\n// Prints '23 things.'\n```\n\n### `reject`\n\nCreate a rejected promise.\n\n```hs\nreject :: Promise p =\u003e a -\u003e p a b\n```\n\nThis function can either take an `Error` object or an string. If a string is\nprovided, it is converted to an `Error`.\n\n```javascript\nimport {reject} from \"dashp\";\n\nconst msg = \"Boom!\";\n\nreject(msg).catch(console.log);\n// Prints `Error`\nreject(new TypeError(msg)).catch(console.log);\n// Prints `TypeError`\n```\n\n### `map`\n\nMap a function over a promise.\n\n```hs\nmap :: Promise p =\u003e (a -\u003e b) -\u003e p a -\u003e p b\n```\n\nIt transforms the value that a promise resolves to and returns a new\npromise. This is equivalent to `promise.then(x =\u003e x + 1)`. The transformation\nis only applied if the promise resolves successfully, it is ignored if the\npromise gets rejected. This function is compliant with the [Static Land\nFunctor specification](SL:functor).\n\n```javascript\nimport {of, map} from \"dashp\";\n\nconst p = of(1);\nconst f = x =\u003e x + 1;\n\nmap(f, p).then(console.log);\n// Prints 2\n```\n\n### `bimap`\n\nMap either the left or right function over a promise.\n\n```hs\nbimap :: Promise p =\u003e (a -\u003e c) -\u003e (b -\u003e d) -\u003e p a b -\u003e p c d\n```\n\nMap the left function over the rejection value, and the right function over\nthe success value of a promise. This function is compliant with the [Static\nLand Bifunctor specification](SL:bifunctor).\n\n```javascript\nimport {of, bimap} from \"dashp\";\n\nconst f = () =\u003e console.log('Boom!');\nconst g = x =\u003e x + 1;\n\nbimap(f, g, of(1)).then(console.log);\n// Prints 2\nbimap(f, g, Promise.reject());\n// Prints 'Boom!'\n```\n\n### `ap`\n\nApply a function wrapped in a promise to a promisified value.\n\n```hs\nap :: Promise p =\u003e p (a -\u003e b) -\u003e p a -\u003e p b\n```\n\nThis function is compliant with the [Static Land Apply\nspecification](SL:apply).\n\n```javascript\nimport {of, ap} from \"dashp\";\n\nconst pf = of(v =\u003e v + 1);\nconst p = of(1);\n\nap(pf, p).then(console.log);\n// Prints 2\n```\n\n### `chain`\n\nMap a function over a promise.\n\n```hs\nchain :: Promise p =\u003e (a -\u003e p b) -\u003e p a -\u003e p b\n```\n\nThis is equivalent to `promise.then(f)`. In practice `chain` works the same as\n`map` since Promises [can't be real Applicative\nFunctors](https://github.com/critocrito/dashp/issues/1). This function is\ncompliant with the [Static Land Chain specification](SL:chain).\n\n```javascript\nimport {of, chain} from \"dashp\";\n\nconst f = x =\u003e of(x + 1);\n\nchain(f, of(0)).then(consol.log);\n// Prints 1\n```\n\n### `compose`\n\nCompose two functions that return promises.\n\n```hs\ncompose :: Promise p =\u003e (a -\u003e p b) -\u003e (b -\u003e p c) -\u003e p a -\u003e p c\n```\n\n`compose` yields a third function that returns a promise. The resulting\ncomposite function is denoted `g∘f : X → Z`, defined by `(g∘f)(x) = g(f(x))`\nfor all `x` in `X`.\n\n```javascript\nimport {of, compose} from \"dashp\";\n\nconst f = x =\u003e of(x + 1);\nconst g = x =\u003e of(x + 5);\nconst h = compose(f, g);\n\nh(10).then(console.log);\n// Prints 16\n```\n\n### `whenElse`\n\nBranch left if the predicate holds, otherwise branch right.\n\n```hs\nwhenElse :: Promise p =\u003e (p a -\u003e Boolean) -\u003e (p a -\u003e p b) -\u003e (p a -\u003e p b) -\u003e p c\n```\n\nThis is a conditional branch like the builtin `if ... else` construct. The\n`predicate`, `consequent` and `alternative` functions can either return a\nvalue or a Promise.\n\n```javascript\nimport {whenElse} from \"dashp\";\n\nconst predicate = userExists;\nconst consequent = updateUser;\nconst alternative = createUser;\n\nwhenElse(predicate, consequent, alternative, user);\n// Calls updateUser if the user exists, and otherwise creates it\n```\n\n### `when`\n\nConditionally call a function if the predicate holds.\n\n```hs\nwhen :: Promise p =\u003e (p a -\u003e Boolean) -\u003e (p a -\u003e p b) -\u003e p c\n```\n\nThis is a conditional branch like the builtin `if` construct. If the predicate\nreturns true, it will return the result of the consequent, otherwise it\nreturns the original value. The `predicate` and `consequent` functions can\neither return a value or a Promise.\n\n```javascript\nimport {when} from \"dashp\";\n\nconst pred = userExists;\nconst consequent = updateUser;\n\nwhen(predicate, consequent, user);\n// Calls updateUser if the user exists, otherwise returns the user\n```\n\n### `unlessElse`\n\nBranch left if the predicate doesn't hold, otherwise branch right.\n\n```hs\nunlexxElse :; Promise p =\u003e (p a -\u003e Boolean) -\u003e (p a -\u003e p b) -\u003e (p a -\u003e p b) -\u003e p c\n```\n\nThis is a conditional branch like the builtin `if (! ... ) ... else`\nconstruct.  The `predicate`, `consequent` and `alternative` functions can\neither return a value or a Promise.\n\n```javascript\nimport {unlessElse} from \"dashp\";\n\nconst predicate = userExists;\nconst consequent = createUser;\nconst alternative = createUser;\n\nunlessEles(predicate, consequent, alternative, user);\n// Creates the user unless it exists, otherwise updates it\n```\n\n### `unless`\n\nConditionally call a function if the predicate doesn't hold.\n\n```hs\nunless :: Promise p =\u003e (p a -\u003e Boolean) -\u003e (p a -\u003e p b) -\u003e p c\n```\n\nThis is a conditional branch like the builtin `if (! ...)` construct. If the\npredicate returns false, it will return the result of the consequent,\notherwise it returns the original value. The `predicate` and `consequent`\nfunctions can either return a value or a Promise.\n\n```javascript\nimport {unless} from \"dashp\";\n\nconst pred = userExists;\nconst consequent = createUser;\n\nunless(predicate, consequent, user);\n// Calls createUser if the user doesn't exist, otherwise returns the user\n```\n\n### `all`\n\nResolve all promises in an array.\n\n```hs\nall :: Promise p =\u003e [p b a] -\u003e p b [a]\n```\n\nThis is equivalent to `Promise.all`, with the difference that it creates a\ncallable function.\n\n```javascript\nimport {all} from \"dashp\";\n\nconst f = all([openFile1(), opeFile2(), openFile3()]);\n\nf().then(console.log);\n// Prints [a, b, c]\n```\n\n### `fold`\n\nReduce a list of values to a single value, using a reduction function.\n\n```hs\nfold :: Promise p =\u003e (p b c -\u003e p b a -\u003e p b c) -\u003e p b c -\u003e [p b a] -\u003e p b c\n```\n\nThis is equivalent to `Array.reduce`.\n\n```javascript\nimport {of, fold} from \"dashp\";\n\nconst f = (acc, x) =\u003e of(acc + x);\nconst xs = [...Array(5).keys()];\n\nfold(f, 0, xs).then(console.log);\n// Prints 10\n```\n\n### `collect`\n\nMap a function over every element of a list.\n\n```hs\ncollect :: Promise p =\u003e (p b a -\u003e p b a) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis is equivalent to `Array.map`. In it's standard version it only resolves\none promise at a time.\n\n```javascript\nimport {of, collect} from \"dashp\";\n\nconst f = x =\u003e of(x + 1);\nconst xs = [...Array(5).keys()];\n\ncollect(f, xs).then(console.log);\n// Prints [1, 2, 3, 4, 5]\n```\n\n### `collect2`\n\nMap a function over every element of a list, resolve two promises in parallel.\n\n```hs\ncollect :: Promise p =\u003e (p b a -\u003e p b a) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis functions works like `collect`, with the only difference that two promises are resolved at the same time.\n\n### `collect3`\n\nMap a function over every element of a list, resolve three promises in parallel.\n\n```hs\ncollect3 :: Promise p =\u003e (p b a -\u003e p b a) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis functions works like `collect`, with the only difference that three promises are resolved at the same time.\n\n### `collect4`\n\nMap a function over every element of a list, resolve four promises in parallel.\n\n```hs\ncollect4 :: Promise p =\u003e (p b a -\u003e p b a) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis functions works like `collect`, with the only difference that four promises are resolved at the same time.\n\n### `collect5`\n\nMap a function over every element of a list, resolve five promises in parallel.\n\n```hs\ncollect5 :: Promise p =\u003e (p b a -\u003e p b a) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis functions works like `collect`, with the only difference that five promises are resolved at the same time.\n\n### `collect6`\n\nMap a function over every element of a list, resolve six promises in parallel.\n\n```hs\ncollect6 :: Promise p =\u003e (p b a -\u003e p b a) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis functions works like `collect`, with the only difference that six promises are resolved at the same time.\n\n### `collect7`\n\nMap a function over every element of a list, resolve seven promises in parallel.\n\n```hs\ncollect7 :: Promise p =\u003e (p b a -\u003e p b a) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis functions works like `collect`, with the only difference that seven promises are resolved at the same time.\n\n### `collect8`\n\nMap a function over every element of a list, resolve eight promises in parallel.\n\n```hs\ncollect8 :: Promise p =\u003e (p b a -\u003e p b a) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis functions works like `collect`, with the only difference that eight promises are resolved at the same time.\n\n### `flatmap`\n\nMap a function over every element of a list and concatenate the results.\n\n```hs\nflatmap :: Promise p =\u003e (p b a -\u003e p b [a]) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis is equivalent to calling `collect` and flattening the resulting list of lists into a single list. In it's standard version it only resolves one promise at a time.\n\n```javascript\nimport {flatmap} from \"dashp\";\n\nconst f = x =\u003e [x, x];\nconst xs = [1, 2];\n\nflatmap(f, xs).then(console.log);\n// Prints [1, 1, 2, 2]\n```\n\n### `flatmap2`\n\nMap a function over every element of a list and concatenate the results, resolve two promises at the same time.\n\n```hs\nflatmap2 :: Promise p =\u003e (p b a -\u003e p b [a]) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis is equivalent to `flatmap`, only that it resolves two promises in parallel.\n\n### `flatmap3`\n\nMap a function over every element of a list and concatenate the results, resolve three promises at the same time.\n\n```hs\nflatmap3 :: Promise p =\u003e (p b a -\u003e p b [a]) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis is equivalent to `flatmap`, only that it resolves three promises in parallel.\n\n### `flatmap4`\n\nMap a function over every element of a list and concatenate the results, resolve four promises at the same time.\n\n```hs\nflatmap4 :: Promise p =\u003e (p b a -\u003e p b [a]) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis is equivalent to `flatmap`, only that it resolves four promises in parallel.\n\n### `flatmap5`\n\nMap a function over every element of a list and concatenate the results, resolve five promises at the same time.\n\n```hs\nflatmap5 :: Promise p =\u003e (p b a -\u003e p b [a]) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis is equivalent to `flatmap`, only that it resolves five promises in parallel.\n\n### `flatmap6`\n\nMap a function over every element of a list and concatenate the results, resolve six promises at the same time.\n\n```hs\nflatmap6 :: Promise p =\u003e (p b a -\u003e p b [a]) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis is equivalent to `flatmap`, only that it resolves six promises in parallel.\n\n### `flatmap7`\n\nMap a function over every element of a list and concatenate the results, resolve seven promises at the same time.\n\n```hs\nflatmap7 :: Promise p =\u003e (p b a -\u003e p b [a]) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis is equivalent to `flatmap`, only that it resolves seven promises in parallel.\n\n### `flatmap8`\n\nMap a function over every element of a list and concatenate the results, resolve eight promises at the same time.\n\n```hs\nflatmap8 :: Promise p =\u003e (p b a -\u003e p b [a]) -\u003e [p b a] -\u003e p b [a]\n```\n\nThis is equivalent to `flatmap`, only that it resolves eight promises in parallel.\n\n### `isPromise`\n\nDetermine whether an object is a promise.\n\n```hs\nisPromise :: a -\u003e Boolean\n```\n\n```javascript\nimport {of, isPromise} from \"dashp\";\n\nconst p = of(23);\n\nisPromise(p);\n// Prints true\n```\n\n### `tap`\n\nCall a function for side effect and return the original value.\n\n```hs\ntap :: Promise p =\u003e (p b a -\u003e ()) -\u003e p b a -\u003e p b a\n```\n\n```javascript\nimport {of, flow, tap} from \"dashp\";\n\nconst f = a =\u003e of(a);\n\nflow([f, tap(console.log)])(23);\n// Print \"23\"\n```\n\n### `tapClone`\n\nCall a function for side effect and return the original value.\n\n```hs\ntap :: Promise p =\u003e (p b a -\u003e ()) -\u003e p b a -\u003e p b a\n```\n\nThis function is like `tap`, but makes a deep clone of the value before\napplying it to the function.\n\n```javascript\nimport {of, flow, tapClone} from \"dashp\";\n\nconst f = a =\u003e of(a);\n\nflow([f, tapClone(console.log)])(23);\n// Print \"23\"\n```\n\n### `caught`\n\nCatch an exception on a promise and call a handler.\n\n```hs\ncaught :: Promise p =\u003e (p b -\u003e p b a) -\u003e p b -\u003e p b a\n```\n\nThis is equivalent to `Promise.catch`.\n\n```javascript\nimport {caught, flow} from \"dashp\";\n\nconst f = () =\u003e new Error(\"Boom\");\n\nflow([f, caught(console.err)]);\n// Prints the exception\n```\n\n### `spread`\n\nCall a variadic function with the value of a promise as it's arguments.\n\n```hs\nspread :: Promise p =\u003e (a -\u003e b) -\u003e p b [a] -\u003e p b a\n```\n\nIf the value is an array, flatten it to the formal parameters of the\nfulfillment handler.\n\n```javascript\nimport {of, flow, spread} from \"dashp\";\n\nconst plus = (x, y) =\u003e x + y;\nconst p = of([1, 2]);\n\nspread(plus, p).then(console.log);\n// Prints 3\n```\n\n### `flow`\n\nCompose functions into a chain.\n\n```hs\nflow :: Promise p =\u003e [(a -\u003e c)] -\u003e p b a -\u003e p b c\n```\n\nCreate a function out of a list of functions, where each successive invocation is supplied the return value of the previous function call. The new function forms a pipe where the results flow from left to right so to speak. This is equivalent to Lodash's `flow` function. It's a shortcut for composing more than two functions.\n\n```javascript\nimport {of, flow} from \"dashp\";\n\nconst f = (x) -\u003e (y) =\u003e of(x + y);\nconst fs = [...Array(5).keys()].map(f);\n\nflow(fs, 0).then(console.log);\n// Prints 10\n```\n\n`flow` treats any occurrence of `caught` as a special case by rewriting the function chains to wrap relevant parts in an exception handler. In order to support a syntax like:\n\n```\nimport {flow, caught} from \"dashp\";\n\nconst boom = () =\u003e { throw new Error; };\nconst notBoom = () =\u003e 23;\n\nflow([\n  boom,\n  notBoom,\n  caught(console.error),\n  notBoom,\n]);\n```\n\n`flow` will parse the function chain for any occurrence of `caught` and rewrite the function chain accordingly to look like this:\n\n```\nflow([\n  x =\u003e caught(console.error, flow([boom, notBoom], x)),\n  notBoom,\n]);\n```\n\n### `flow2`\n\nLift a composed function chain over two arguments.\n\n```hs\nflow2 :: Promise p =\u003e [(a -\u003e a -\u003e c) (c -\u003e d)] -\u003e p b a -\u003e p b a -\u003e p b d\n```\n\nThis function works like `flow`, but it accepts two arguments, that are lifted into the first function of the chain.\n\n### `flow3`\n\nLift a composed function chain over three arguments.\n\n```hs\nflow3 :: Promise p =\u003e [(a -\u003e a -\u003e a -\u003e c) (c -\u003e d)] -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b d\n```\n\nThis function works like `flow`, but it accepts three arguments, that are lifted into the first function of the chain.\n\n### `flow4`\n\nLift a composed function chain over four arguments.\n\n```hs\nflow4 :: Promise p =\u003e [(a -\u003e a -\u003e a -\u003e a -\u003e c) (c -\u003e d)] -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b d\n```\n\nThis function works like `flow`, but it accepts four arguments, that are lifted into the first function of the chain.\n\n### `flow5`\n\nLift a composed function chain over five arguments.\n\n```hs\nflow5 :: Promise p =\u003e [(a -\u003e a -\u003e a -\u003e a -\u003e a -\u003e c) (c -\u003e d)] -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b d\n```\n\nThis function works like `flow`, but it accepts five arguments, that are lifted into the first function of the chain.\n\n### `flow6`\n\nLift a composed function chain over six arguments.\n\n```hs\nflow6 :: Promise p =\u003e [(a -\u003e a -\u003e a -\u003e a -\u003e a -\u003e a -\u003e c) (c -\u003e d)] -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b d\n```\n\nThis function works like `flow`, but it accepts six arguments, that are lifted into the first function of the chain.\n\n### `flow7`\n\nLift a composed function chain over seven arguments.\n\n```hs\nflow7 :: Promise p =\u003e [(a -\u003e a -\u003e a -\u003e a -\u003e a -\u003e a -\u003e a -\u003e c) (c -\u003e d)] -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b d\n```\n\nThis function works like `flow`, but it accepts seven arguments, that are lifted into the first function of the chain.\n\n### `flow8`\n\nLift a composed function chain over eight arguments.\n\n```hs\nflow8 :: Promise p =\u003e [(a -\u003e a -\u003e a -\u003e a -\u003e a -\u003e a -\u003e a -\u003e a -\u003e c) (c -\u003e d)] -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b d\n```\n\nThis function works like `flow`, but it accepts eight arguments, that are lifted into the first function of the chain.\n\n### `constant`\n\nCreate a function that always returns the same value.\n\n```hs\nconstant :: a -\u003e (b -\u003e Promise a)\n```\n\n```javascript\nimport {constant} from \"dashp\";\n\nconst f = constant(\"Hello\");\n\nf().then(console.log);\n// Prints \"Hello\"\n```\n\n### `lift2`\n\nLift a binary function over two promises.\n\n```hs\nlift2 :: Promise p =\u003e (a -\u003e a -\u003e a) -\u003e p b a -\u003e p b a -\u003e p b a\n```\n\n```javascript\nimport {of, lift2} from \"dashp\";\n\nconst f = (x, y) =\u003e x + y;\n\nlift2(f, of(1), of(2)).then(console.log);\n// Prints 3\n```\n\n### `lift3`\n\nLift a ternary function over three promises.\n\n```hs\nlift3 :: Promise p =\u003e (a -\u003e a -\u003e a -\u003e a) -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a\n```\n\n```javascript\nimport {of, lift3} from \"dashp\";\n\nconst f = (x, y, z) =\u003e x + y + z;\n\nlift3(f, of(1), of(2), of(3)).then(console.log);\n// Prints 6\n```\n\n### `lift4`\n\nLift a quartary function over four promises.\n\n```hs\nlift4 :: Promise p =\u003e (a -\u003e a -\u003e a -\u003e a -\u003e a) -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a -\u003e p b a\n```\n\n```javascript\nimport {of, lift4} from \"dashp\";\n\nconst f = (w, x, y, z) =\u003e w + x + y + z;\n\nlift4(f, of(1), of(2), of(3), of(4)).then(console.log);\n// Prints 10\n```\n\n### `delay`\n\nDelay the resolution of a promise chain.\n\n```hs\ndelay :: Promise p =\u003e x -\u003e p b a -\u003e p b a\n```\n\nThe first arguments is the delay in milliseconds.\n\n```javascript\nimport {of, delay} from \"dashp\";\n\ndelay(100, of(23)).then(console.log);\n// Waits 100 ms and print 23.\n```\n\n### `retry`\n\nCall an action, and retry it in case it fails.\n\n```hs\nretry :: Promise p =\u003e p b a -\u003e p b a\n```\n\nAn action is retried up to five times with an increasing timeout. The action\ncan be a function as well. In it's standard version, the action function\ndoesn't receive any arguments.\n\n```javascript\nimport {retry} from \"dashp\";\n\n// Retries `fetchUser` in case of failure.\nretry(fetchUser).then(console.log).catch(console.error);\n```\n\n## License\n\n[GPL 3.0 licensed](LICENSE)\n\n\u003c!-- References --\u003e\n\n[SL]: https://github.com/rpominov/static-land\n[SL:functor]: https://github.com/rpominov/static-land/blob/master/docs/spec.md#functor\n[SL:chain]: https://github.com/rpominov/static-land/blob/master/docs/spec.md#chain\n[SL:apply]: https://github.com/rpominov/static-land/blob/master/docs/spec.md#apply\n[SL:applicative]: https://github.com/rpominov/static-land/blob/master/docs/spec.md#applicative\n[SL:bifunctor]: https://github.com/rpominov/static-land/blob/master/docs/spec.md#bifunctor\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcritocrito%2Fdashp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcritocrito%2Fdashp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcritocrito%2Fdashp/lists"}