{"id":13431894,"url":"https://github.com/fluture-js/Fluture","last_synced_at":"2025-03-16T22:32:46.551Z","repository":{"id":37743302,"uuid":"53253439","full_name":"fluture-js/Fluture","owner":"fluture-js","description":"🦋 Fantasy Land compliant (monadic) alternative to Promises","archived":false,"fork":false,"pushed_at":"2024-04-22T19:36:55.000Z","size":2212,"stargazers_count":2472,"open_issues_count":13,"forks_count":84,"subscribers_count":26,"default_branch":"master","last_synced_at":"2024-05-01T19:48:03.006Z","etag":null,"topics":["algebraic-data-types","async","cancellation","control-flow","fantasy-land","fluture","functional-programming","future","monad","promise","sanctuary"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fluture-js.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["Avaq"]}},"created_at":"2016-03-06T12:20:57.000Z","updated_at":"2024-05-05T10:38:45.344Z","dependencies_parsed_at":"2023-02-10T05:35:14.395Z","dependency_job_id":"6a63f312-f321-46f6-891e-0675bd7bdcbc","html_url":"https://github.com/fluture-js/Fluture","commit_stats":{"total_commits":985,"total_committers":32,"mean_commits":30.78125,"dds":0.349238578680203,"last_synced_commit":"1d925dea0008cd0324e757c179c12a7ea6b5aaca"},"previous_names":[],"tags_count":110,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluture-js%2FFluture","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluture-js%2FFluture/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluture-js%2FFluture/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluture-js%2FFluture/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fluture-js","download_url":"https://codeload.github.com/fluture-js/Fluture/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221668940,"owners_count":16860763,"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":["algebraic-data-types","async","cancellation","control-flow","fantasy-land","fluture","functional-programming","future","monad","promise","sanctuary"],"created_at":"2024-07-31T02:01:06.819Z","updated_at":"2024-10-27T11:30:35.868Z","avatar_url":"https://github.com/fluture-js.png","language":"JavaScript","readme":"# [![Fluture](logo.png)](#butterfly)\n\n[![Build Status][]](https://github.com/fluture-js/Fluture/actions?query=branch%3Amaster+workflow%3ATest)\n[![Code Coverage][]](https://codecov.io/gh/fluture-js/Fluture/branch/master)\n[![Dependency Status][]](https://david-dm.org/fluture-js/Fluture)\n[![NPM Package][]](https://www.npmjs.com/package/fluture)\n[![Gitter Chat][]](https://gitter.im/fluture-js/Fluture)\n\n[Build Status]: https://github.com/fluture-js/Fluture/workflows/Test/badge.svg\n[Code Coverage]: https://img.shields.io/codecov/c/github/fluture-js/Fluture/master.svg\n[Dependency Status]: https://img.shields.io/david/fluture-js/Fluture.svg\n[NPM Package]: https://img.shields.io/npm/v/fluture.svg\n[Gitter Chat]: https://img.shields.io/gitter/room/fluture-js/Fluture.svg?colorB=blue\n\nFluture offers a control structure similar to Promises, Tasks, Deferreds, and\nwhat-have-you. Let's call them Futures.\n\nMuch like Promises, Futures represent the value arising from the success or\nfailure of an asynchronous operation (I/O). Though unlike Promises, Futures are\n*lazy* and adhere to [the *monadic* interface](#interoperability).\n\nSome of the features provided by Fluture include:\n\n* [Cancellation](#cancellation).\n* [Resource management utilities](#resource-management).\n* [Stack safe composition and recursion](#stack-safety).\n* [Integration](#sanctuary) with [Sanctuary][S].\n* [A pleasant debugging experience](#debugging).\n\nFor more information:\n\n* [API documentation](#documentation)\n* [Article: Introduction to Fluture - A Functional Alternative to Promises][10]\n* [Wiki: Compare Futures to Promises][wiki:promises]\n* [Wiki: Compare Fluture to similar libraries][wiki:similar]\n* [Video: Monad a Day - Futures by @DrBoolean][5]\n\n## Installation\n\n### With NPM\n\n```console\n$ npm install --save fluture\n```\n\n### Bundled from a CDN\n\nTo load Fluture directly into a browser, a code pen, or [Deno][], use one of\nthe following downloads from the JSDelivr content delivery network. These are\nsingle files that come with all of Fluture's dependencies pre-bundled.\n\n- [Fluture Script][]: A JavaScript file that adds `Fluture` to the global\n  scope. Ideal for older browsers and code pens.\n- [Fluture Script Minified][]: The same as above, but minified.\n- [Fluture Module][]: An EcmaScript module with named exports. Ideal for Deno\n  or modern browsers.\n- [Fluture Module Minified][]: A minified EcmaScript module without TypeScript\n  typings. Not recommended for Deno.\n\n[Fluture Script]: https://cdn.jsdelivr.net/gh/fluture-js/Fluture@14.0.0/dist/bundle.js\n[Fluture Script Minified]: https://cdn.jsdelivr.net/gh/fluture-js/Fluture@14.0.0/dist/bundle.min.js\n[Fluture Module]: https://cdn.jsdelivr.net/gh/fluture-js/Fluture@14.0.0/dist/module.js\n[Fluture Module Minified]: https://cdn.jsdelivr.net/gh/fluture-js/Fluture@14.0.0/dist/module.min.js\n\n## Usage\n\n### EcmaScript Module\n\nFluture is written as modular JavaScript.\n\n- On Node 12 and up, Fluture can be loaded directly with `import 'fluture'`.\n- On some older (minor) Node versions, you may need to import from\n  `'fluture/index.js'` instead, and/or pass `--experimental-modules` to `node`.\n- On Node versions below 12, the [esm loader][esm] can be used. Alternatively,\n  there is a [CommonJS Module](#commonjs-module) available.\n- Modern browsers can run Fluture directly. If you'd like to try this out,\n  I recommend installing Fluture with [Pika][] or [Snowpack][]. You can also\n  try the [bundled module](#bundled-from-a-cdn) to avoid a package manager.\n- For older browsers, use a bundler such as [Rollup][] or WebPack. Besides the\n  module system, Fluture uses purely ES5-compatible syntax, so the source does\n  not have to be transpiled after bundling. Alternatively, there is a\n  [CommonJS Module](#commonjs-module) available.\n\n```js\nimport {readFile} from 'fs'\nimport {node, encase, chain, map, fork} from 'fluture'\n\nconst getPackageName = file =\u003e (\n  node (done =\u003e { readFile (file, 'utf8', done) })\n  .pipe (chain (encase (JSON.parse)))\n  .pipe (map (x =\u003e x.name))\n)\n\ngetPackageName ('package.json')\n.pipe (fork (console.error) (console.log))\n```\n\n### CommonJS Module\n\nAlthough the Fluture source uses the EcmaScript module system,\nthe `main` file points to a CommonJS version of Fluture.\n\nOn older environments one or more of the following functions may need to be\npolyfilled: [`Object.create`][JS:Object.create],\n[`Object.assign`][JS:Object.assign] and [`Array.isArray`][JS:Array.isArray].\n\n```js\nconst fs = require ('fs')\nconst Future = require ('fluture')\n\nconst getPackageName = function (file) {\n  return Future.node (function (done) { fs.readFile (file, 'utf8', done) })\n  .pipe (Future.chain (Future.encase (JSON.parse)))\n  .pipe (Future.map (function (x) { return x.name }))\n}\n\ngetPackageName ('package.json')\n.pipe (Future.fork (console.error) (console.log))\n```\n\n## Documentation\n\n### Table of contents\n\n\u003cdetails open\u003e\u003csummary\u003eGeneral\u003c/summary\u003e\n\n- [Installation instructions](#installation)\n- [Usage instructions](#usage)\n- [About the Fluture project](#butterfly)\n- [On interoperability with other libraries](#interoperability)\n- [How to read the type signatures](#type-signatures)\n- [How cancellation works](#cancellation)\n- [On stack safety](#stack-safety)\n- [Debugging with Fluture](#debugging)\n- [Casting Futures to String](#casting-futures-to-string)\n- [Usage with Sanctuary](#sanctuary)\n- [Using multiple versions of Fluture alongside each other](#incompatible-fluture-versions)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eCreating new Futures\u003c/summary\u003e\n\n- [`Future`: Create a possibly cancellable Future](#future)\n- [`resolve`: Create a resolved Future](#resolve)\n- [`reject`: Create a rejected Future](#reject)\n- [`after`: Create a Future that resolves after a timeout](#after)\n- [`rejectAfter`: Create a Future that rejects after a timeout](#rejectafter)\n- [`go`: Create a \"coroutine\" using a generator function](#go)\n- [`attempt`: Create a Future using a possibly throwing function](#attempt)\n- [`attemptP`: Create a Future using a Promise-returning function](#attemptp)\n- [`node`: Create a Future using a Node-style callback](#node)\n- [`encase`: Convert a possibly throwing function to a Future function](#encase)\n- [`encaseP`: Convert a Promise-returning function to a Future function](#encasep)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eConverting between Nodeback APIs and Futures\u003c/summary\u003e\n\n- [`node`: Create a Future using a Node-style callback](#node)\n- [`done`: Consume a Future by providing a Nodeback](#done)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eConverting between Promises and Futures\u003c/summary\u003e\n\n- [`attemptP`: Create a Future using a Promise-returning function](#attemptp)\n- [`encaseP`: Convert a Promise-returning function to a Future function](#encasep)\n- [`promise`: Convert a Future to a Promise](#promise)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eTransforming and combining Futures\u003c/summary\u003e\n\n- [`pipe`: Apply a function to a Future in a fluent method chain](#pipe)\n- [`map`: Synchronously process the success value in a Future](#map)\n- [`bimap`: Synchronously process the success or failure value in a Future](#bimap)\n- [`chain`: Asynchronously process the success value in a Future](#chain)\n- [`bichain`: Asynchronously process the success or failure value in a Future](#bichain)\n- [`swap`: Swap the success with the failure value](#swap)\n- [`mapRej`: Synchronously process the failure value in a Future](#maprej)\n- [`chainRej`: Asynchronously process the failure value in a Future](#chainrej)\n- [`coalesce`: Coerce success and failure values into the same success value](#coalesce)\n- [`ap`: Combine the success values of multiple Futures using a function](#ap)\n- [`pap`: Combine the success values of multiple Futures in parallel using a function](#pap)\n- [`and`: Logical *and* for Futures](#and)\n- [`alt`: Logical *or* for Futures](#alt)\n- [`lastly`: Run a Future after the previous settles](#lastly)\n- [`race`: Race two Futures against each other](#race)\n- [`both`: Await both success values from two Futures](#both)\n- [`parallel`: Await all success values from many Futures](#parallel)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eConsuming/forking Futures\u003c/summary\u003e\n\n- [`fork`: Standard way to run a Future and get at its result](#fork)\n- [`forkCatch`: Fork with exception recovery](#forkcatch)\n- [`value`: Shorter variant of `fork` for Futures sure to succeed](#value)\n- [`done`: Nodeback style `fork`](#done)\n- [`promise`: Convert a Future to a Promise](#promise)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eConcurrency related utilities and data structures\u003c/summary\u003e\n\n- [`pap`: Combine the success values of multiple Futures in parallel using a function](#pap)\n- [`race`: Race two Futures against each other](#race)\n- [`both`: Await both success values from two Futures](#both)\n- [`parallel`: Await all success values from many Futures](#parallel)\n- [`ConcurrentFuture`: A separate data-type for doing algebraic concurrency](#concurrentfuture)\n- [`alt`: Behaves like `race` on `ConcurrentFuture` instances](#alt)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eResource management\u003c/summary\u003e\n\n- [`hook`: Safely create and dispose resources](#hook)\n- [`lastly`: Run a Future after the previous settles](#lastly)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eOther utilities\u003c/summary\u003e\n\n- [`pipe`: Apply a function to a Future in a fluent method chain](#pipe)\n- [`cache`: Cache a Future so that it can be forked multiple times](#cache)\n- [`isFuture`: Determine whether a value is a Fluture compatible Future](#isfuture)\n- [`never`: A Future that never settles](#never)\n- [`debugMode`: Configure Fluture's debug mode](#debugmode)\n- [`context`: The debugging context of a Future instance](#context)\n\n\u003c/details\u003e\n\n### Butterfly\n\nThe name \"Fluture\" is a conjunction of \"FL\" (the acronym to [Fantasy Land][FL])\nand \"future\". Fluture means butterfly in Romanian: A creature one might expect\nto see in Fantasy Land.\n\nCredit goes to Erik Fuente for styling the logo, and [WEAREREASONABLEPEOPLE][9]\nfor sponsoring the project.\n\n### Interoperability\n\n[\u003cimg src=\"https://raw.github.com/fantasyland/fantasy-land/master/logo.png\" align=\"right\" width=\"82\" height=\"82\" alt=\"Fantasy Land\" /\u003e][FL]\n\n* `Future` implements [Fantasy Land][FL] 1.0+ -compatible\n  `Alt`, `Bifunctor`, `Monad`, and `ChainRec`\n  (`of`, `ap`, `alt`, `map`, `bimap`, `chain`, `chainRec`).\n* `Future.Par` implements [Fantasy Land 3][FL] -compatible\n  `Alternative` (`of`, `zero`, `map`, `ap`, `alt`).\n* The Future and ConcurrentFuture representatives contain `@@type` properties\n  for [Sanctuary Type Identifiers][STI].\n* The Future and ConcurrentFuture instances contain `@@show` properties for\n  [Sanctuary Show][SS].\n\n### Type signatures\n\nThe various function signatures are provided in a small language referred to as\nHindley-Milner notation.\n\nIn summary, the syntax is as follows: `InputType -\u003e OutputType`. Now,\nbecause functions in Fluture are [curried][Guide:currying], the \"output\" of a\nfunction is often *another function*. In Hindley-Milner that's simply written\nas `InputType -\u003e InputToSecondFunction -\u003e OutputType` and so forth.\n\nBy convention, types starting with an upper-case letter are\n[concrete types](#types). When they start with a lower-case letter they're\n*type variables*. You can think of these type variables as generic types.\nSo `a -\u003e b` denotes a function from generic type `a` to generic type `b`.\n\nFinally, through so-called [*constraints*](#type-classes), type variables can\nbe forced to conform to an \"interface\" (or *Type Class* in functional jargon).\nFor example, `MyInterface a =\u003e a -\u003e b`, denotes a function from generic type\n`a` to generic type `b`, *where `a` must implement `MyInterface`*.\n\nYou can read in depth about [Hindley-Milner in JavaScript][Guide:HM] here.\n\n#### Types\n\nThe concrete types you will encounter throughout this documentation:\n\n- **Future** - Instances of Future provided by\n  [compatible versions](#incompatible-fluture-versions) of Fluture.\n- **ConcurrentFuture** - Futures wrapped with ([`Future.Par`](#concurrentfuture)).\n- **Promise a b** - Values which conform to the [Promises/A+ specification][7]\n  and have a rejection reason of type `a` and a resolution value of type `b`.\n- **Nodeback a b** - A Node-style callback; A function of signature `(a | Nil, b) -\u003e x`.\n- **Pair a b** - An array with exactly two elements: `[a, b]`.\n- **Iterator** - Objects with `next`-methods which conform to the [Iterator protocol][3].\n- **Cancel** - The nullary [cancellation](#cancellation) functions returned from computations.\n- **Throwing e a b** - A function from `a` to `b` that may throw an exception `e`.\n- **List** - Fluture's internal linked-list structure: `{ head :: Any, tail :: List }`.\n- **Context** - Fluture's internal debugging context object:\n  `{ tag :: String, name :: String, stack :: String }`.\n\n#### Type classes\n\nSome signatures contain [constrained type variables][Guide:constraints].\nGenerally, these constraints express that some value must conform to a\n[Fantasy Land][FL]-specified interface.\n\n- **Functor** - [Fantasy Land Functor][FL:functor] conformant values.\n- **Bifunctor** - [Fantasy Land Bifunctor][FL:bifunctor] conformant values.\n- **Chain** - [Fantasy Land Chain][FL:chain] conformant values.\n- **Apply** - [Fantasy Land Apply][FL:apply] conformant values.\n- **Alt** - [Fantasy Land Alt][FL:alt] conformant values.\n\n### Cancellation\n\nCancellation is a system whereby running Futures get an opportunity to stop\nwhat they're doing and release resources that they were holding, when the\nconsumer indicates it is no longer interested in the result.\n\nTo cancel a Future, it must be unsubscribed from. Most of the\n[consumption functions](#consuming-futures) return an `unsubscribe` function.\nCalling it signals that we are no longer interested in the result. After\ncalling `unsubscribe`, Fluture guarantees that our callbacks will not be\ncalled; but more importantly: a cancellation signal is sent upstream.\n\nThe cancellation signal travels all the way back to the source (with the\nexception of cached Futures - see [`cache`](#cache)), allowing all parties\nalong the way to clean up.\n\nWith the [`Future` constructor](#future), we can provide a custom cancellation\nhandler by returning it from the computation. Let's see what this looks like:\n\n```js\n// We use the Future constructor to create a Future instance.\nconst eventualAnswer = Future (function computeTheAnswer (rej, res) {\n\n  // We give the computer time to think about the answer, which is 42.\n  const timeoutId = setTimeout (res, 60000, 42)\n\n  // Here is how we handle cancellation. This signal is received when nobody\n  // is interested in the answer any more.\n  return function onCancel () {\n    // Clearing the timeout releases the resources we were holding.\n    clearTimeout (timeoutId)\n  }\n\n})\n\n// Now, let's fork our computation and wait for an answer. Forking gives us\n// the unsubscribe function.\nconst unsubscribe = fork (log ('rejection')) (log ('resolution')) (eventualAnswer)\n\n// After some time passes, we might not care about the answer any more.\n// Calling unsubscribe will send a cancellation signal back to the source,\n// and trigger the onCancel function.\nunsubscribe ()\n```\n\nMany natural sources in Fluture have cancellation handlers of their own.\n[`after`](#after), for example, does exactly what we've done just now: calling\n`clearTimeout`.\n\nFinally, Fluture unsubscribes from Futures that it forks *for us*, when it no\nlonger needs the result. For example, both Futures passed into [race](#race)\nare forked, but once one of them produces a result, the other is unsubscribed\nfrom, triggering cancellation. This means that generally, unsubscription and\ncancellation is fully managed for us behind the scenes.\n\n### Stack safety\n\nFluture interprets our transformations in a stack safe way.\nThis means that none of the following operations result in a\n`RangeError: Maximum call stack size exceeded`:\n\n```js\n\u003e const add1 = x =\u003e x + 1\n\n\u003e let m = resolve (1)\n\n\u003e for (let i = 0; i \u003c 100000; i++) {\n.   m = map (add1) (m)\n. }\n\n\u003e fork (log ('rejection')) (log ('resolution')) (m)\n[resolution]: 100001\n```\n\n```js\n\u003e const m = (function recur (x) {\n.   const mx = resolve (x + 1)\n.   return x \u003c 100000 ? chain (recur) (mx) : mx\n. }(1))\n\n\u003e fork (log ('rejection')) (log ('resolution')) (m)\n[resolution]: 100001\n```\n\nTo learn more about memory and stack usage under different types of recursion,\nsee (or execute) [`scripts/test-mem`](scripts/test-mem).\n\n### Debugging\n\nFirst and foremost, Fluture type-checks all of its input and throws TypeErrors\nwhen incorrect input is provided. The messages they carry are designed to\nprovide enough insight to figure out what went wrong.\n\nSecondly, Fluture catches exceptions that are thrown asynchronously, and\nexposes them to you in one of two ways:\n\n1. By throwing an Error when it happens.\n2. By calling your [exception handler](#forkcatch) with an Error.\n\nThe original exception isn't used because it might have been any value.\nInstead, a regular JavaScript Error instance whose properties are based on the\noriginal exception is created. Its properties are as follows:\n\n- `name`: Always just `\"Error\"`.\n- `message`: The original error message, or a message describing the value.\n- `reason`: The original value that was caught by Fluture.\n- `context`: A linked list of \"context\" objects. This is used to create the\n  `stack` property, and you generally don't need to look at it. If debug mode\n  is not enabled, the list is always empty.\n- `stack`: The stack trace of the original exception if it had one, or the\n  Error's own stack trace otherwise. If debug mode (see below) is enabled,\n  additional stack traces from the steps leading up to the crash are included.\n- `future`: The instance of [`Future`](#future) that was being\n  [consumed](#consuming-futures) when the exception happened. Often\n  [printing it as a String](#casting-futures-to-string) can yield useful\n  information. You can also try to consume it in isolation to better identify\n  what's going wrong.\n\nFinally, as mentioned, Fluture has a [debug mode](#debugmode) wherein\nadditional contextual information across multiple JavaScript ticks is\ncollected, included as an extended \"async stack trace\" on Errors, and\n[exposed on Future instances](#context).\n\nDebug mode can have a significant impact on performance, and uses up memory,\nso I would advise against using it in production.\n\n### Casting Futures to String\n\nThere are multiple ways to print a Future to String. Let's take a simple\ncomputation as an example:\n\n```js\nconst add = a =\u003e b =\u003e a + b;\nconst eventualAnswer = ap (resolve (22)) (map (add) (resolve (20)));\n```\n\n1. Casting it to String directly by calling `String(eventualAnswer)` or\n   `eventualAnswer.toString()` will yield an approximation of the code that\n   was used to create the Future. In this case:\n\n   ```js\n   \"ap (resolve (22)) (map (a =\u003e b =\u003e a + b) (resolve (20)))\"\n   ```\n\n2. Casting it to String using `JSON.stringify(eventualAnswer, null, 2)` will\n   yield a kind of abstract syntax tree.\n\n   ```json\n   {\n     \"$\": \"fluture/Future@5\",\n     \"kind\": \"interpreter\",\n     \"type\": \"transform\",\n     \"args\": [\n       {\n         \"$\": \"fluture/Future@5\",\n         \"kind\": \"interpreter\",\n         \"type\": \"resolve\",\n         \"args\": [\n           20\n         ]\n       },\n       [\n         {\n           \"$\": \"fluture/Future@5\",\n           \"kind\": \"transformation\",\n           \"type\": \"ap\",\n           \"args\": [\n             {\n               \"$\": \"fluture/Future@5\",\n               \"kind\": \"interpreter\",\n               \"type\": \"resolve\",\n               \"args\": [\n                 22\n               ]\n             }\n           ]\n         },\n         {\n           \"$\": \"fluture/Future@5\",\n           \"kind\": \"transformation\",\n           \"type\": \"map\",\n           \"args\": [\n             null\n           ]\n         }\n       ]\n     ]\n   }\n   ```\n\n### Sanctuary\n\nWhen using this module with [Sanctuary Def][$] (and [Sanctuary][S] by\nextension) one might run into the following issue:\n\n```js\n\u003e import S from 'sanctuary'\n\n\u003e import {resolve} from 'fluture'\n\n\u003e S.I (resolve (1))\n! TypeError: Since there is no type of which all the above values are members,\n. the type-variable constraint has been violated.\n```\n\nThis happens because Sanctuary Def needs to know about the types created by\nFluture to determine whether the type-variables are consistent.\n\nTo let Sanctuary know about these types, we can obtain the type definitions\nfrom [`fluture-sanctuary-types`][FST] and pass them to [`S.create`][S:create]:\n\n```js\n\u003e import sanctuary from 'sanctuary'\n\n\u003e import {env as flutureEnv} from 'fluture-sanctuary-types'\n\n\u003e import {resolve} from 'fluture'\n\n\u003e const S = sanctuary.create ({checkTypes: true, env: sanctuary.env.concat (flutureEnv)})\n\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (S.I (resolve (42)))\n[resolution]: 42\n```\n\n### Incompatible Fluture Versions\n\nMost versions of Fluture understand how to consume instances from most other\nversions, even across Fluture's major releases. This allows for different\npackages that depend on Fluture to interact.\n\nHowever, sometimes it's unavoidable that a newer version of Fluture is released\nthat can no longer understand older versions, and vice-versa. This only ever\nhappens on a major release, and will be mentioned in the breaking change log.\nWhen two incompatible versions of Fluture meet instances, they do their best to\nissue a clear error message about it.\n\nWhen this happens, you need to manually convert the older instance to a newer\ninstance of Future. When [`isFuture`](#isfuture) returns `false`, a conversion\nis necessary. You can also apply this trick if the Future comes from another\nlibrary similar to Fluture.\n\n```js\nconst NoFuture = require ('incompatible-future')\n\nconst incompatible = NoFuture.of ('Hello')\n\nconst compatible = Future ((rej, res) =\u003e {\n  return NoFuture.fork (rej) (res) (incompatible)\n})\n\nboth (compatible) (resolve ('world'))\n```\n\n### Creating Futures\n\n#### Future\n\n```hs\nFuture :: ((a -\u003e Undefined, b -\u003e Undefined) -\u003e Cancel) -\u003e Future a b\n```\n\nCreates a Future with the given computation. A computation is a function which\ntakes two callbacks. Both are continuations for the computation. The first is\n`reject`, commonly abbreviated to `rej`; The second is `resolve`, or `res`.\nWhen the computation is finished (possibly asynchronously) it may call the\nappropriate continuation with a failure or success value.\n\nAdditionally, the computation must return a nullary function containing\ncancellation logic. See [Cancellation](#cancellation).\n\nIf you find that there is no way to cancel your computation, you can return a\n`noop` function as a cancellation function. However, at this point there is\nusually a more fitting way to [create that Future](#creating-futures)\n(like for example via [`node`](#node)).\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (Future (function computation (reject, resolve) {\n.        const t = setTimeout (resolve, 20, 42)\n.        return () =\u003e clearTimeout (t)\n.      }))\n[resolution]: 42\n```\n\n#### resolve\n\n```hs\nresolve :: b -\u003e Future a b\n```\n\nCreates a Future which immediately resolves with the given value.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (resolve (42))\n[answer]: 42\n```\n\n#### reject\n\n```hs\nreject :: a -\u003e Future a b\n```\n\nCreates a Future which immediately rejects with the given value.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (reject ('It broke!'))\n[rejection]: \"It broke!\"\n```\n\n#### after\n\n```hs\nafter :: Number -\u003e b -\u003e Future a b\n```\n\nCreates a Future which resolves with the given value after\nthe given number of milliseconds.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (after (20) (42))\n[resolution]: 42\n```\n\n#### rejectAfter\n\n```hs\nrejectAfter :: Number -\u003e a -\u003e Future a b\n```\n\nCreates a Future which rejects with the given reason after the given number of\nmilliseconds.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (rejectAfter (20) ('It broke!'))\n[rejection]: \"It broke!\"\n```\n\n#### go\n\n```hs\ngo :: (() -\u003e Iterator) -\u003e Future a b\n```\n\nA way to do `async`/`await` with Futures, similar to Promise Coroutines or\nHaskell Do-notation.\n\nTakes a function which returns an [Iterator](#types), commonly a\ngenerator-function, and chains every produced Future over the previous.\n\n```js\n\u003e fork (log ('rejection')) (log ('resolution')) (go (function*() {\n.   const thing = yield after (20) ('world')\n.   const message = yield after (20) ('Hello ' + thing)\n.   return message + '!'\n. }))\n[resolution]: \"Hello world!\"\n```\n\nA rejected Future short-circuits the whole coroutine.\n\n```js\n\u003e fork (log ('rejection')) (log ('resolution')) (go (function*() {\n.   const thing = yield reject ('It broke!')\n.   const message = yield after (20) ('Hello ' + thing)\n.   return message + '!'\n. }))\n[rejection]: \"It broke!\"\n```\n\nTo handle rejections *inside* the coroutine, we need to [`coalesce`](#coalesce)\nthe error into our control domain.\n\nI recommend using coalesce with an [`Either`][S:Either].\n\n```js\n\u003e const control = coalesce (S.Left) (S.Right)\n\n\u003e fork (log ('rejection')) (log ('resolution')) (go (function*() {\n.   const thing = yield control (reject ('It broke!'))\n.   return S.either (x =\u003e `Oh no! ${x}`)\n.                   (x =\u003e `Yippee! ${x}`)\n.                   (thing)\n. }))\n[resolution]: \"Oh no! It broke!\"\n```\n\n#### attempt\n\n```hs\nattempt :: Throwing e Undefined r -\u003e Future e r\n```\n\nCreates a Future which resolves with the result of calling the given function,\nor rejects with the error thrown by the given function.\n\nShort for [`encase (f) (undefined)`](#encase).\n\n```js\n\u003e const data = {foo: 'bar'}\n\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (attempt (() =\u003e data.foo.bar.baz))\n[rejection]: new TypeError (\"Cannot read property 'baz' of undefined\")\n```\n\n#### attemptP\n\n```hs\nattemptP :: (Undefined -\u003e Promise a b) -\u003e Future a b\n```\n\nCreate a Future which when forked spawns a Promise using the given function and\nresolves with its resolution value, or rejects with its rejection reason.\n\nShort for [`encaseP (f) (undefined)`](#encasep).\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (attemptP (() =\u003e Promise.resolve (42)))\n[resolution]: 42\n```\n\n#### node\n\n```hs\nnode :: (Nodeback e r -\u003e x) -\u003e Future e r\n```\n\nCreates a Future which rejects with the first argument given to the function,\nor resolves with the second if the first is not present.\n\nNote that this function **does not support cancellation**.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (node (done =\u003e done (null, 42)))\n[resolution]: 42\n```\n\n#### encase\n\n```hs\nencase :: Throwing e a r -\u003e a -\u003e Future e r\n```\n\nTakes a function and a value, and returns a Future which when forked calls the\nfunction with the value and resolves with the result. If the function throws\nan exception, it is caught and the Future will reject with the exception.\n\nApplying `encase` with a function `f` creates a \"safe\" version of `f`. Instead\nof throwing exceptions, the encased version always returns a Future.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (encase (JSON.parse) ('{\"foo\" = \"bar\"}'))\n[rejection]: new SyntaxError ('Unexpected token =')\n```\n\n#### encaseP\n\n```hs\nencaseP :: (a -\u003e Promise e r) -\u003e a -\u003e Future e r\n```\n\nTurns Promise-returning functions into Future-returning functions.\n\nTakes a function which returns a Promise, and a value, and returns a Future.\nWhen forked, the Future calls the function with the value to produce the\nPromise, and resolves with its resolution value, or rejects with its rejection\nreason.\n\n```js\n\u003e encaseP (fetch) ('https://api.github.com/users/Avaq')\n. .pipe (chain (encaseP (res =\u003e res.json ())))\n. .pipe (map (user =\u003e user.name))\n. .pipe (fork (log ('rejection')) (log ('resolution')))\n[resolution]: \"Aldwin Vlasblom\"\n```\n\n### Transforming Futures\n\n#### map\n\n```hs\nmap :: Functor m =\u003e (a -\u003e b) -\u003e m a -\u003e m b\n```\n\nTransforms the resolution value inside the Future or [Functor][FL:functor],\nand returns a Future or Functor with the new value. The transformation is only\napplied to the resolution branch: if the Future is rejected, the transformation\nis ignored.\n\nSee also [`chain`](#chain) and [`mapRej`](#maprej).\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (map (x =\u003e x + 1) (resolve (41)))\n[resolution]: 42\n```\n\nFor comparison, an approximation with Promises is:\n\n```js\n\u003e Promise.resolve (41)\n. .then (x =\u003e x + 1)\n. .then (log ('resolution'), log ('rejection'))\n[resolution]: 42\n```\n\n#### bimap\n\n```hs\nbimap :: Bifunctor m =\u003e (a -\u003e c) -\u003e (b -\u003e d) -\u003e m a b -\u003e m c d\n```\n\nMaps the left function over the rejection reason, or the right function over\nthe resolution value, depending on which is present. Can be used on any\n[Bifunctor][FL:bifunctor].\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (bimap (x =\u003e x + '!') (x =\u003e x + 1) (resolve (41)))\n[resolution]: 42\n\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (bimap (x =\u003e x + '!') (x =\u003e x + 1) (reject ('It broke!')))\n[rejection]: \"It broke!!\"\n```\n\nFor comparison, an approximation with Promises is:\n\n```js\n\u003e Promise.resolve (41)\n. .then (x =\u003e x + 1, x =\u003e Promise.reject (x + '!'))\n. .then (log ('resolution'), log ('rejection'))\n[resolution]: 42\n\n\u003e Promise.reject ('It broke!')\n. .then (x =\u003e x + 1, x =\u003e Promise.reject (x + '!'))\n. .then (log ('resolution'), log ('rejection'))\n[rejection]: \"It broke!!\"\n```\n\n#### chain\n\n```hs\nchain :: Chain m =\u003e (a -\u003e m b) -\u003e m a -\u003e m b\n```\n\nSequence a new Future or [Chain][FL:chain] using the resolution value from\nanother. Similarly to [`map`](#map), `chain` expects a function. But instead\nof returning the new *value*, chain expects a Future (or instance of the same\nChain) to be returned.\n\nThe transformation is only applied to the resolution branch: if the Future is\nrejected, the transformation is ignored.\n\nSee also [`chainRej`](#chainrej).\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (chain (x =\u003e resolve (x + 1)) (resolve (41)))\n[resolution]: 42\n```\n\nFor comparison, an approximation with Promises is:\n\n```js\n\u003e Promise.resolve (41)\n. .then (x =\u003e Promise.resolve (x + 1))\n. .then (log ('resolution'), log ('rejection'))\n[resolution]: 42\n```\n\n#### bichain\n\n```hs\nbichain :: (a -\u003e Future c d) -\u003e (b -\u003e Future c d) -\u003e Future a b -\u003e Future c d\n```\n\nSequence a new Future using either the resolution or the rejection value from\nanother. Similarly to [`bimap`](#bimap), `bichain` expects two functions. But\ninstead of returning the new *value*, bichain expects Futures to be returned.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (bichain (resolve) (x =\u003e resolve (x + 1)) (resolve (41)))\n[resolution]: 42\n\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (bichain (x =\u003e resolve (x + 1)) (resolve) (reject (41)))\n[resolution]: 42\n```\n\nFor comparison, an approximation with Promises is:\n\n```js\n\u003e Promise.resolve (41)\n. .then (x =\u003e Promise.resolve (x + 1), Promise.resolve)\n. .then (log ('resolution'), log ('rejection'))\n[resolution]: 42\n\n\u003e Promise.reject (41)\n. .then (Promise.resolve, x =\u003e Promise.resolve (x + 1))\n. .then (log ('resolution'), log ('rejection'))\n[resolution]: 42\n```\n\n#### swap\n\n```hs\nswap :: Future a b -\u003e Future b a\n```\n\nSwap the rejection and resolution branches.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (swap (resolve (42)))\n[rejection]: 42\n\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (swap (reject (42)))\n[resolution]: 42\n```\n\n#### mapRej\n\n```hs\nmapRej :: (a -\u003e c) -\u003e Future a b -\u003e Future c b\n```\n\nMap over the **rejection** reason of the Future. This is like [`map`](#map),\nbut for the rejection branch.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (mapRej (s =\u003e `Oh no! ${s}`) (reject ('It broke!')))\n[rejection]: \"Oh no! It broke!\"\n```\n\nFor comparison, an approximation with Promises is:\n\n```js\n\u003e Promise.reject ('It broke!')\n. .then (null, s =\u003e Promise.reject (`Oh no! ${s}`))\n. .then (log ('resolution'), log ('rejection'))\n[rejection]: \"Oh no! It broke!\"\n```\n\n#### chainRej\n\n```hs\nchainRej :: (a -\u003e Future c b) -\u003e Future a b -\u003e Future c b\n```\n\nChain over the **rejection** reason of the Future. This is like\n[`chain`](#chain), but for the rejection branch.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (chainRej (s =\u003e resolve (`${s} But it's all good.`)) (reject ('It broke!')))\n[resolution]: \"It broke! But it's all good.\"\n```\n\nFor comparison, an approximation with Promises is:\n\n```js\n\u003e Promise.reject ('It broke!')\n. .then (null, s =\u003e `${s} But it's all good.`)\n. .then (log ('resolution'), log ('rejection'))\n[resolution]: \"It broke! But it's all good.\"\n```\n\n#### coalesce\n\n```hs\ncoalesce :: (a -\u003e c) -\u003e (b -\u003e c) -\u003e Future a b -\u003e Future d c\n```\n\nApplies the left function to the rejection value, or the right function to the\nresolution value, depending on which is present, and resolves with the result.\n\nThis provides a convenient means to ensure a Future is always resolved. It can\nbe used with other type constructors, like [`S.Either`][S:Either], to maintain\na representation of failure.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (coalesce (S.Left) (S.Right) (resolve ('hello'))\n[resolution]: Right (\"hello\")\n\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (coalesce (S.Left) (S.Right) (reject ('It broke!'))\n[resolution]: Left (\"It broke!\")\n```\n\nFor comparison, an approximation with Promises is:\n\n```js\n\u003e Promise.resolve ('hello')\n. .then (S.Right, S.Left)\n. .then (log ('resolution'), log ('rejection'))\n[resolution]: Right (\"hello\")\n\n\u003e Promise.reject ('It broke!')\n. .then (S.Right, S.Left)\n. .then (log ('resolution'), log ('rejection'))\n[resolution]: Left (\"It broke!\")\n```\n\n### Combining Futures\n\n#### ap\n\n```hs\nap :: Apply m =\u003e m a -\u003e m (a -\u003e b) -\u003e m b\n```\n\nApplies the function contained in the right-hand Future or [Apply][FL:apply]\nto the value contained in the left-hand Future or Apply. This process can be\nrepeated to gradually fill out multiple function arguments of a curried\nfunction, as shown below.\n\nNote that the Futures will be executed in sequence - not in parallel\\* -\nbecause of the Monadic nature of Futures. The execution order is, as\nspecified by Fantasy Land, `m (a -\u003e b)` first followed by `m a`.\nSo that's *right before left*.\n\n\\* Have a look at [`pap`](#pap) for an `ap` function that runs its arguments\n   in parallel. If you must use `ap` (because you're creating a generalized\n   function), but still want Futures passed into it to run in parallel, then\n   you could use [ConcurrentFuture](#concurrentfuture) instead.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (ap (resolve (7)) (ap (resolve (49)) (resolve (x =\u003e y =\u003e x - y))))\n[resolution]: 42\n```\n\n#### pap\n\n```hs\npap :: Future a b -\u003e Future a (b -\u003e c) -\u003e Future a c\n```\n\nHas the same signature and function as [`ap`](#ap), but runs the two Futures\ngiven to it in parallel. See also [ConcurrentFuture](#concurrentfuture) for a\nmore general way to achieve this.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (pap (resolve (7)) (pap (resolve (49)) (resolve (x =\u003e y =\u003e x - y))))\n[resolution]: 42\n```\n\n#### alt\n\n```hs\nalt :: Alt f =\u003e f a -\u003e f a -\u003e f a\n```\n\nSelect one of two [Alts](#types).\n\nBehaves like logical *or* on [`Future`](#future) instances, returning a new\nFuture which either resolves with the first resolution value, or rejects with\nthe last rejection reason. We can use it if we want a computation to run only\nif another has failed.\n\nNote that the Futures will be executed in sequence - not in parallel\\* -\nbecause of the Monadic nature of Futures. The *right* Future is evaluated\nbefore the *left* Future.\n\nSee also [`and`](#and) and [`lastly`](#lastly).\n\n\\* If you'd like to use a parallel implementation of `alt`, you could simply\n   use [`race`](#race). Alternatively you could wrap your Future instances\n   with [`Par`](#concurrentfuture) before passing them to `alt`.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (alt (resolve ('left')) (resolve ('right')))\n[resolution]: \"right\"\n\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (alt (resolve ('left')) (reject ('It broke!')))\n[resolution]: \"left\"\n```\n\n#### and\n\n```hs\nand :: Future a c -\u003e Future a b -\u003e Future a c\n```\n\nLogical *and* for Futures.\n\nReturns a new Future which either rejects with the first rejection reason, or\nresolves with the last resolution value once and if both Futures resolve. We\ncan use it if we want a computation to run only after another has succeeded.\nThe *right* Future is evaluated before the *left* Future.\n\nSee also [`alt`](#alt) and [`lastly`](#lastly).\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (and (resolve ('left')) (resolve ('right')))\n[resolution]: \"left\"\n\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (and (resolve ('left')) (reject ('It broke!')))\n[rejection]: \"It broke!\"\n```\n\n#### lastly\n\n```hs\nlastly :: Future a c -\u003e Future a b -\u003e Future a b\n```\n\nRun a second Future after the first settles (successfully or unsuccessfully).\nRejects with the rejection reason from the first or second Future, or resolves\nwith the resolution value from the first Future. This can be used to run a\ncomputation after another settles, successfully or unsuccessfully.\n\nIf you're looking to clean up resources after running a computation which\nacquires them, you should use [`hook`](#hook), which has many more fail-safes\nin place.\n\nSee also [`and`](#and) and [`alt`](#alt).\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (lastly (encase (log ('lastly')) ('All done!')) (resolve (42)))\n[lastly]: \"All done!\"\n[resolution]: 42\n```\n\n### Consuming Futures\n\n#### fork\n\n```hs\nfork :: (a -\u003e Any) -\u003e (b -\u003e Any) -\u003e Future a b -\u003e Cancel\n```\n\nExecute the computation represented by a Future, passing `reject` and `resolve`\ncallbacks to continue once there is a result.\n\nThis function is called `fork` because it literally represents a fork in our\nprogram: a point where a single code-path splits in two. It is recommended to\nkeep the number of calls to `fork` at a minimum for this reason. The more\nforks, the higher the code complexity.\n\nGenerally, one only needs to call `fork` in a single place in the entire\nprogram.\n\nAfter we `fork` a Future, the computation will start running. If the program\ndecides halfway through that it's no longer interested in the result of the\ncomputation, it can call the `unsubscribe` function returned by `fork`. See\n[Cancellation](#cancellation).\n\nIf an exception was encountered during the computation, it will be re-thrown\nby `fork` and likely not be catchable. You can handle it using\n`process.on('uncaughtException')` in Node, or use [`forkCatch`](#forkcatch).\n\nAlmost all code examples in Fluture use `fork` to run the computation. There\nare some variations on `fork` that serve different purposes below.\n\n#### forkCatch\n\n```hs\nforkCatch :: (Error -\u003e Any) -\u003e (a -\u003e Any) -\u003e (b -\u003e Any) -\u003e Future a b -\u003e Cancel\n```\n\nAn advanced version of [fork](#fork) that allows us to react to a fatal error\nin a custom way. Fatal errors occur when unexpected exceptions are thrown, when\nthe Fluture API is used incorrectly, or when resources couldn't be disposed.\n\nThe exception handler will always be called with an instance of `Error`,\nindependent of what caused the crash.\n\n**Using this function is a trade-off;**\n\nGenerally it's best to let a program crash and restart when an a fatal error\noccurs. Restarting is the surest way to restore the memory that was allocated\nby the program to an expected state.\n\nBy using `forkCatch`, we can keep our program alive after a fatal error, which\ncan be very beneficial when the program is being used by multiple clients.\nHowever, since fatal errors might indicate that something, somewhere has\nentered an invalid state, it's probably still best to restart our program upon\nencountering one.\n\nSee [Debugging](#debugging) for information about the Error object that is\npassed to your exception handler.\n\n```js\n\u003e forkCatch (log ('fatal error'))\n.           (log ('rejection'))\n.           (log ('resolution'))\n.           (map (x =\u003e x.foo) (resolve (null)))\n[fatal error]: new Error (\"Cannot read property 'foo' of null\")\n```\n\n#### value\n\n```hs\nvalue :: (b -\u003e Any) -\u003e Future a b -\u003e Cancel\n```\n\nLike [`fork`](#fork) but for the resolution branch only. Only use this function\nif you are sure the Future is going to be resolved, for example; after using\n[`coalesce`](#coalesce). If the Future rejects, `value` will throw an Error.\n\nAs with [`fork`](#fork), `value` returns an `unsubscribe` function. See\n[Cancellation](#cancellation).\n\n```js\n\u003e value (log ('resolution')) (resolve (42))\n[resolution]: 42\n```\n\n#### done\n\n```hs\ndone :: Nodeback a b -\u003e Future a b -\u003e Cancel\n```\n\nRun the Future using a [Nodeback](#types) as the continuation.\n\nThis is like [`fork`](#fork), but instead of taking two unary functions, it\ntakes a single binary function.\n\nAs with [`fork`](#fork), `done` returns an `unsubscribe` function. See\n[Cancellation](#cancellation).\n\n```js\n\u003e done ((err, val) =\u003e log ('resolution') (val)) (resolve (42))\n[resolution]: 42\n```\n\n#### promise\n\n```hs\npromise :: Future Error a -\u003e Promise Error a\n```\n\nRun the Future and get a Promise to represent its continuation.\n\nReturns a Promise which resolves with the resolution value, or rejects with\nthe rejection reason of the Future.\n\nIf an exception was encountered during the computation, the promise will reject\nwith it. I recommend using [`coalesce`](#coalesce) before `promise` to ensure\nthat exceptions and rejections are not mixed into the Promise rejection branch.\n\nCancellation capabilities are lost when using `promise` to consume the Future.\n\n```js\n\u003e promise (resolve (42)) .then (log ('resolution'))\n[resolution]: 42\n\n\u003e promise (reject ('failure')) .then (log ('resolution'), log ('rejection'))\n[rejection]: \"failure\"\n```\n\n### Parallelism\n\n#### race\n\n```hs\nrace :: Future a b -\u003e Future a b -\u003e Future a b\n```\n\nRace two Futures against each other. Creates a new Future which resolves or\nrejects with the resolution or rejection value of the first Future to settle.\n\nWhen one Future settles, the other gets cancelled automatically.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (race (after (15) ('left')) (after (30) ('right')))\n[resolution]: \"left\"\n```\n\n#### both\n\n```hs\nboth :: Future a b -\u003e Future a c -\u003e Future a (Pair b c)\n```\n\nRun two Futures in parallel and get a [`Pair`](#types) of the results. When\neither Future rejects, the other Future will be cancelled and the resulting\nFuture will reject.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (both (after (15) ('left')) (after (30) ('right')))\n[resolution]: [\"left\", \"right\"]\n```\n\n#### parallel\n\n```hs\nparallel :: PositiveInteger -\u003e Array (Future a b) -\u003e Future a (Array b)\n```\n\nCreates a Future which when forked runs all Futures in the given Array in\nparallel, ensuring no more than `limit` Futures are running at once.\n\nIn the following example, we're running up to 5 Futures in parallel. Every\nFuture takes about 20ms to settle, which means the result should appear after\nabout 40ms.\n\nIf we use `1` for the limit, the Futures would run in sequence, causing the\nresult to appear only after 200ms.\n\nWe can also use `Infinity` as the limit. This would create a function similar\nto `Promise.all`, which always runs all Futures in parallel. This can easily\ncause the computation to consume too many resources, however, so I would\nadvise using a number roughly equal to maximum size of Array you think your\nprogram should handle.\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (parallel (5) (Array.from (Array (10) .keys ()) .map (after (20))))\n[resolution]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n```\n\nWhen one Future rejects, all currently running Futures will be cancelled and\nthe resulting Future will reject. If you want to settle all Futures, even if\nsome may fail, you can use `parallel` in combination with\n[coalesce](#coalesce).\n\n```js\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (parallel (2) ([resolve (42), reject ('It broke!')]\n.                     .map (coalesce (S.Left) (S.Right))))\n[resolution]: [Right (42), Left (\"It broke!\")]\n```\n\n#### ConcurrentFuture\n\nThe `ConcurrentFuture` type is very similar to the `Future` type, except that\nit has *parallel* semantics where `Future` has *sequential* semantics.\n\nThese sematics are most notable in the implementation of Applicative for\n`ConcurrentFuture`. When using [`ap`](#ap) on two ConcurrentFutures, they\nrun parallely, whereas regular `Future` instances would've run sequentially.\nThis means that `ConcurrentFuture` cannot be a Monad, which is why we have\nit as a separate type.\n\nThe implementation of Alternative on `ConcurrentFuture` has parallel semantics\nas well. Whereas [`alt`](#alt) on regular Futures uses the failure effect to\ndetermine a winner, on ConcurrentFutures *timing* is used, and the winner will\nbe whichever ConcurrentFuture settled first.\n\nThe idea is that we can switch back and forth between `Future` and\n`ConcurrentFuture`, using [`Par`](#par) and [`seq`](#seq), to get sequential or\nconcurrent behaviour respectively. It's a useful type to pass to abstractions\nthat don't know about Future-specific functions like [`parallel`](#parallel) or\n[`race`](#race), but *do* know how to operate on Apply and Alternative.\n\n```js\n//Some dummy values\nconst x = 41;\nconst f = a =\u003e a + 1;\n\n//The following two are equal ways to construct a ConcurrentFuture\nconst parx = S.of (Par) (x)\nconst parf = Par (S.of (Future) (f))\n\n//We can make use of parallel apply\nvalue (log ('resolution')) (seq (ap (parx) (parf)))\n[resolution]: 42\n\n//Concurrent sequencing\nvalue (log ('resolution')) (seq (S.sequence (Par) ([parx, parx, parx])))\n[resolution]: [41, 41, 41]\n\n//And concurrent alt\nvalue (log ('resolution')) (alt (after (15) ('left')) (after (30) ('right')))\n[resolution]: \"left\"\n```\n\n##### Par\n\n```hs\nPar :: Future a b -\u003e ConcurrentFuture a b\n```\n\nConverts a Future to a ConcurrentFuture.\n\n##### seq\n\nConverts a ConcurrentFuture to a Future.\n\n```hs\nseq :: ConcurrentFuture a b -\u003e Future a b\n```\n\n### Resource management\n\nFunctions listed under this category allow for more fine-grained control over\nthe flow of acquired values.\n\n#### hook\n\n```hs\nhook :: Future a b -\u003e (b -\u003e Future c d) -\u003e (b -\u003e Future a e) -\u003e Future a e\n```\n\nCombines resource acquisition, consumption, and disposal in such a way that you\ncan be sure that a resource will always be disposed if it was acquired, even if\nan exception is thrown during consumption; Sometimes referred to as bracketing.\n\nThe signature is like `hook (acquire, dispose, consume)`, where:\n\n- `acquire` is a Future which might create connections, open files, etc.\n- `dispose` is a function that takes the result from `acquire` and should be\n  used to clean up (close connections etc). The Future it returns must\n  resolve, and its resolution value is ignored. If it rejects, a fatal error\n  is raised which can only be handled with [`forkCatch`](#forkcatch).\n- `consume` is another Function takes the result from `acquire`, and may be\n  used to perform any arbitrary computations using the resource.\n\nTypically, you'd want to partially apply this function with the first two\narguments (acquisition and disposal), as shown in the example.\n\n```js\n\u003e import {open, read, close} from 'fs'\n\n\u003e const withFile = hook (node (done =\u003e open ('package.json', 'r', done)))\n.                       (fd =\u003e node (done =\u003e close (fd, done)))\n\n\u003e fork (log ('rejection'))\n.      (log ('resolution'))\n.      (withFile (fd =\u003e node (done =\u003e (\n.        read (fd, Buffer.alloc (1), 0, 1, null, (e, _, x) =\u003e done (e, x)))\n.      )))\n[resolution]: \u003cBuffer 7b\u003e\n```\n\nWhen a hooked Future is cancelled while acquiring its resource, nothing else\nwill happen. When it's cancelled after acquistion completes, however, the\ndisposal will still run, and if it fails, an exception will be thrown.\n\nIf you have multiple resources that you'd like to consume all at once, you can\nuse [Fluture Hooks](https://github.com/fluture-js/fluture-hooks) to combine\nmultiple hooks into one.\n\n### Utility functions\n\n#### pipe\n\n```hs\nFuture.prototype.pipe :: Future a b ~\u003e (Future a b -\u003e c) -\u003e c\n```\n\nA method available on all Futures to allow arbitrary functions over Futures to\nbe included in a fluent-style method chain.\n\nYou can think of this as a fallback for the [ESNext pipe operator (`|\u003e`)][2].\n\n```js\n\u003e resolve (x =\u003e y =\u003e x * y)\n. .pipe (ap (after (20) (Math.PI)))\n. .pipe (ap (after (20) (13.37)))\n. .pipe (map (Math.round))\n. .pipe (fork (log ('rejection')) (log ('resolution')))\n[resolution]: 42\n```\n\n#### cache\n\n```hs\ncache :: Future a b -\u003e Future a b\n```\n\nReturns a Future which caches the resolution value or rejection reason of the\ngiven Future so that whenever it's forked, it can load the value from cache\nrather than re-executing the underlying computation.\n\nThis essentially turns a unicast Future into a multicast Future, allowing\nmultiple consumers to subscribe to the same result. The underlying computation\nis never [cancelled](#cancellation) unless *all* consumers unsubscribe before\nit completes.\n\n**There is a glaring drawback to using `cache`**, which is that returned\nFutures are no longer referentially transparent, making reasoning about them\nmore difficult and refactoring code that uses them harder.\n\n```js\n\u003e import {readFile} from 'fs'\n\n\u003e const eventualPackageName = (\n.   node (done =\u003e readFile ('package.json', 'utf8', done))\n.   .pipe (chain (encase (JSON.parse)))\n.   .pipe (chain (encase (x =\u003e x.name)))\n.   .pipe (map (data =\u003e {\n.      log ('debug') ('Read, parsed, and traversed the package data')\n.      return data\n.    }))\n. )\n\n\u003e fork (log ('rejection')) (log ('resolution')) (eventualPackageName)\n[debug]: \"Read, parsed, and traversed the package data\"\n[resolution]: \"Fluture\"\n\n\u003e fork (log ('rejection')) (log ('resolution')) (eventualPackageName)\n[debug]: \"Read, parsed, and traversed the package data\"\n[resolution]: \"Fluture\"\n\n\u003e const eventualCachedPackageName = cache (eventualPackageName)\n\n\u003e fork (log ('rejection')) (log ('resolution')) (eventualCachedPackageName)\n[debug]: \"Read, parsed, and traversed the package data\"\n[resolution]: \"Fluture\"\n\n\u003e fork (log ('rejection')) (log ('resolution')) (eventualCachedPackageName)\n[resolution]: \"Fluture\"\n```\n\n#### isFuture\n\n```hs\nisFuture :: a -\u003e Boolean\n```\n\nReturns true for [Futures](#types) and false for everything else. This function\n(and [`S.is`][S:is]) also return `true` for instances of Future that were\ncreated within other contexts. It is therefore recommended to use this over\n`instanceof`, unless your intent is to explicitly check for Futures created\nusing the exact `Future` constructor you're testing against.\n\n```js\n\u003e isFuture (resolve (42))\ntrue\n\n\u003e isFuture (42)\nfalse\n```\n\n#### never\n\n```hs\nnever :: Future a b\n```\n\nA Future that never settles. Can be useful as an initial value when reducing\nwith [`race`](#race), for example.\n\n#### isNever\n\n```hs\nisNever :: a -\u003e Boolean\n```\n\nReturns `true` if the given input is a `never`.\n\n#### extractLeft\n\n```hs\nextractLeft :: Future a b -\u003e Array a\n```\n\nReturns an array whose only element is the rejection reason of the Future.\nIn many cases it will be impossible to extract this value; In those cases, the\narray will be empty. This function is meant to be used for type introspection:\nit is **not** the correct way to [consume a Future](#consuming-futures).\n\n#### extractRight\n\n```hs\nextractRight :: Future a b -\u003e Array b\n```\n\nReturns an array whose only element is the resolution value of the Future.\nIn many cases it will be impossible to extract this value; In those cases, the\narray will be empty. This function is meant to be used for type introspection:\nit is **not** the correct way to [consume a Future](#consuming-futures).\n\n#### debugMode\n\n```hs\ndebugMode :: Boolean -\u003e Undefined\n```\n\nEnable or disable Fluture's debug mode. Debug mode is disabled by default.\nPass `true` to enable, or `false` to disable.\n\n```js\ndebugMode (true)\n```\n\nFor more information, see [Debugging](#debugging) and [Context](#context).\n\n#### context\n\n```hs\nFuture.prototype.context :: Future a b ~\u003e List Context\n```\n\nA linked list of debugging contexts made available on every instance of\n`Future`. When [debug mode](#debugmode) is disabled, the list is always empty.\n\nThe context objects have `stack` properties which contain snapshots of the\nstacktraces leading up to the creation of the `Future` instance. They are used\nby Fluture to generate contextual stack traces.\n\n## License\n\n[MIT licensed](LICENSE)\n\n\u003c!-- References --\u003e\n\n[wiki:similar]:         https://github.com/fluture-js/Fluture/wiki/Comparison-of-Future-Implementations\n[wiki:promises]:        https://github.com/fluture-js/Fluture/wiki/Comparison-to-Promises\n\n[FL]:                   https://github.com/fantasyland/fantasy-land\n[FL:alt]:               https://github.com/fantasyland/fantasy-land#alt\n[FL:alternative]:       https://github.com/fantasyland/fantasy-land#alternative\n[FL:functor]:           https://github.com/fantasyland/fantasy-land#functor\n[FL:chain]:             https://github.com/fantasyland/fantasy-land#chain\n[FL:apply]:             https://github.com/fantasyland/fantasy-land#apply\n[FL:bifunctor]:         https://github.com/fantasyland/fantasy-land#bifunctor\n[FL:chainrec]:          https://github.com/fantasyland/fantasy-land#chainrec\n\n[JS:Object.create]:     https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create\n[JS:Object.assign]:     https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign\n[JS:Array.isArray]:     https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray\n\n[S]:                    https://sanctuary.js.org/\n[S:Either]:             https://sanctuary.js.org/#either-type\n[S:is]:                 https://sanctuary.js.org/#is\n[S:create]:             https://sanctuary.js.org/#create\n[S:join]:               https://sanctuary.js.org/#join\n\n[SS]:                   https://github.com/sanctuary-js/sanctuary-show\n[STI]:                  https://github.com/sanctuary-js/sanctuary-type-identifiers\n[FST]:                  https://github.com/fluture-js/fluture-sanctuary-types\n\n[$]:                    https://github.com/sanctuary-js/sanctuary-def\n\n[Rollup]:               https://rollupjs.org/\n[Pika]:                 https://www.pikapkg.com/\n[Snowpack]:             https://www.snowpack.dev/\n[esm]:                  https://github.com/standard-things/esm\n[Deno]:                 https://deno.land/\n\n[Guide:HM]:             https://mostly-adequate.gitbook.io/mostly-adequate-guide/ch07\n[Guide:constraints]:    https://mostly-adequate.gitbook.io/mostly-adequate-guide/ch07#constraints\n[Guide:currying]:       https://mostly-adequate.gitbook.io/mostly-adequate-guide/ch04\n\n[1]:                    https://en.wikipedia.org/wiki/Continuation-passing_style\n[2]:                    https://github.com/tc39/proposal-pipeline-operator\n[3]:                    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#iterator\n[5]:                    https://vimeo.com/106008027\n[7]:                    https://promisesaplus.com/\n[9]:                    https://wearereasonablepeople.nl/\n[10]:                   https://dev.to/avaq/fluture-a-functional-alternative-to-promises-21b\n","funding_links":["https://github.com/sponsors/Avaq"],"categories":["JavaScript","functional-programming"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffluture-js%2FFluture","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffluture-js%2FFluture","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffluture-js%2FFluture/lists"}