Showing preview only (415K chars total). Download the full file or copy to clipboard to get everything.
Repository: Avaq/Fluture
Branch: master
Commit: 1d925dea0008
Files: 139
Total size: 383.8 KB
Directory structure:
gitextract_iludrmak/
├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .github/
│ ├── FUNDING.yml
│ ├── dependabot.yml
│ └── workflows/
│ └── test.yml
├── .gitignore
├── .npmrc
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── bench/
│ ├── .eslintrc.json
│ ├── .npmrc
│ ├── README.md
│ ├── fluture.js
│ ├── folktale.js
│ ├── package.json
│ └── promise.js
├── dist/
│ ├── bundle.js
│ └── module.js
├── index.cjs.js
├── index.d.ts
├── index.js
├── package.json
├── rollup.config.dist.js
├── rollup.config.js
├── scripts/
│ ├── bench.js
│ ├── distribute
│ ├── test-esm
│ └── test-mem
├── src/
│ ├── after.js
│ ├── alt.js
│ ├── and.js
│ ├── ap.js
│ ├── attempt-p.js
│ ├── attempt.js
│ ├── bichain.js
│ ├── bimap.js
│ ├── both.js
│ ├── cache.js
│ ├── chain-rej.js
│ ├── chain.js
│ ├── coalesce.js
│ ├── done.js
│ ├── encase-p.js
│ ├── encase.js
│ ├── extract-left.js
│ ├── extract-right.js
│ ├── fork-catch.js
│ ├── fork.js
│ ├── future.js
│ ├── go.js
│ ├── hook.js
│ ├── internal/
│ │ ├── const.js
│ │ ├── debug.js
│ │ ├── error.js
│ │ ├── iteration.js
│ │ ├── list.js
│ │ ├── parallel.js
│ │ ├── predicates.js
│ │ ├── timing.js
│ │ └── utils.js
│ ├── lastly.js
│ ├── map-rej.js
│ ├── map.js
│ ├── node.js
│ ├── pap.js
│ ├── par.js
│ ├── parallel.js
│ ├── promise.js
│ ├── race.js
│ ├── reject-after.js
│ ├── seq.js
│ ├── swap.js
│ └── value.js
└── test/
├── arbitraries.js
├── assertions.js
├── build/
│ ├── main.js
│ └── require.js
├── integration/
│ └── main.js
├── prop/
│ ├── 0.algebra.js
│ ├── 0.fantasy-land.js
│ ├── 1.fantasy-libs.js
│ └── 2.arbitrary.js
├── types/
│ └── map.test-d.ts
├── unit/
│ ├── 0.debug.js
│ ├── 0.error.js
│ ├── 0.iteration.js
│ ├── 0.list.js
│ ├── 0.predicates.js
│ ├── 0.utils.js
│ ├── 1.future.js
│ ├── 1.is-future.js
│ ├── 1.is-never.js
│ ├── 1.never.js
│ ├── 1.pipe.js
│ ├── 2.done.js
│ ├── 2.extract-left.js
│ ├── 2.extract-right.js
│ ├── 2.fork-catch.js
│ ├── 2.fork.js
│ ├── 2.promise.js
│ ├── 2.value.js
│ ├── 3.after.js
│ ├── 3.attempt-p.js
│ ├── 3.attempt.js
│ ├── 3.cache.js
│ ├── 3.crash.js
│ ├── 3.encase-p.js
│ ├── 3.encase.js
│ ├── 3.go.js
│ ├── 3.hook.js
│ ├── 3.node.js
│ ├── 3.parallel.js
│ ├── 3.reject-after.js
│ ├── 3.reject.js
│ ├── 3.resolve.js
│ ├── 4.alt.js
│ ├── 4.and.js
│ ├── 4.ap.js
│ ├── 4.bichain.js
│ ├── 4.bimap.js
│ ├── 4.both.js
│ ├── 4.chain-rej.js
│ ├── 4.chain.js
│ ├── 4.coalesce.js
│ ├── 4.lastly.js
│ ├── 4.map-rej.js
│ ├── 4.map.js
│ ├── 4.pap.js
│ ├── 4.race.js
│ ├── 4.swap.js
│ ├── 5.chain-rec.js
│ ├── 5.par.js
│ └── 5.seq.js
└── util/
├── futures.js
├── props.js
└── util.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
================================================
FILE: .eslintignore
================================================
/test/build/require.js
================================================
FILE: .eslintrc.json
================================================
{
"root": true,
"extends": ["warp"],
"parserOptions": {
"ecmaVersion": 2015,
"sourceType": "module"
},
"globals": {
"setTimeout": false,
"clearTimeout": false,
"Promise": false
},
"rules": {
"space-before-blocks": [2, "never"],
"consistent-this": [2, "_this"],
"semi": [2, "always", {"omitLastInOneLineBlock": true}],
"curly": ["off"],
"func-style": ["off"],
"prefer-template": ["off"],
"prefer-arrow-callback": ["off"],
"no-use-before-define": ["off"],
"max-statements-per-line": ["off"],
"prefer-rest-params": ["off"],
"class-methods-use-this": ["off"],
"camelcase": ["off"],
"indent": ["off"],
"func-name-matching": ["off"],
"no-console": 2,
"eqeqeq": [2, "smart"],
"no-eq-null": ["off"],
"no-param-reassign": ["off"],
"no-shadow": ["off"],
"keyword-spacing": ["off"],
"no-plusplus": ["off"],
"operator-assignment": ["off"],
"one-var": ["off"],
"generator-star-spacing": ["error", {"before": false, "after": false}],
"no-mixed-operators": ["off"],
"capitalized-comments": ["off"],
"init-declarations": ["off"],
"function-call-argument-newline": ["off"],
"no-multi-assign": ["off"],
"no-invalid-this": ["off"]
},
"overrides": [
{
"files": ["test/**"],
"env": {"node": true},
"globals": {"Promise": false},
"rules": {
"arrow-body-style": ["off"],
"no-sequences": ["off"],
"max-len": ["off"],
"space-before-function-paren": ["error", "always"]
}
}
]
}
================================================
FILE: .github/FUNDING.yml
================================================
github: [Avaq]
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
reviewers:
- Avaq
================================================
FILE: .github/workflows/test.yml
================================================
name: Test
on:
pull_request:
push:
branches:
- master
- 11.x
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v1
- name: Install NodeJS
uses: actions/setup-node@v1
with:
node-version: 18.x
- name: Install Dependencies
run: npm install
- name: Execute Tests
run: npm test
- name: Upload Coverage Report
run: npm run coverage:upload
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
================================================
FILE: .gitignore
================================================
/bench/node_modules/
/coverage/
/node_modules/
/perf/
/index.cjs
================================================
FILE: .npmrc
================================================
package-lock=false
================================================
FILE: CHANGELOG.md
================================================
# Change Log
Please refer to the [release notes](https://github.com/fluture-js/Fluture/releases).
================================================
FILE: CONTRIBUTING.md
================================================
# Contribution guide
## Making a contribution
* Fork and clone the project
* Commit changes to a branch named after the work that was done
* Make sure the tests pass locally
* Create a pull request
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2020 Aldwin Vlasblom
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# [](#butterfly)
[![Build Status][]](https://github.com/fluture-js/Fluture/actions?query=branch%3Amaster+workflow%3ATest)
[![Code Coverage][]](https://codecov.io/gh/fluture-js/Fluture/branch/master)
[![Dependency Status][]](https://david-dm.org/fluture-js/Fluture)
[![NPM Package][]](https://www.npmjs.com/package/fluture)
[![Gitter Chat][]](https://gitter.im/fluture-js/Fluture)
[Build Status]: https://github.com/fluture-js/Fluture/workflows/Test/badge.svg
[Code Coverage]: https://img.shields.io/codecov/c/github/fluture-js/Fluture/master.svg
[Dependency Status]: https://img.shields.io/david/fluture-js/Fluture.svg
[NPM Package]: https://img.shields.io/npm/v/fluture.svg
[Gitter Chat]: https://img.shields.io/gitter/room/fluture-js/Fluture.svg?colorB=blue
Fluture offers a control structure similar to Promises, Tasks, Deferreds, and
what-have-you. Let's call them Futures.
Much like Promises, Futures represent the value arising from the success or
failure of an asynchronous operation (I/O). Though unlike Promises, Futures are
*lazy* and adhere to [the *monadic* interface](#interoperability).
Some of the features provided by Fluture include:
* [Cancellation](#cancellation).
* [Resource management utilities](#resource-management).
* [Stack safe composition and recursion](#stack-safety).
* [Integration](#sanctuary) with [Sanctuary][S].
* [A pleasant debugging experience](#debugging).
For more information:
* [API documentation](#documentation)
* [Article: Introduction to Fluture - A Functional Alternative to Promises][10]
* [Wiki: Compare Futures to Promises][wiki:promises]
* [Wiki: Compare Fluture to similar libraries][wiki:similar]
* [Video: Monad a Day - Futures by @DrBoolean][5]
## Installation
### With NPM
```console
$ npm install --save fluture
```
### Bundled from a CDN
To load Fluture directly into a browser, a code pen, or [Deno][], use one of
the following downloads from the JSDelivr content delivery network. These are
single files that come with all of Fluture's dependencies pre-bundled.
- [Fluture Script][]: A JavaScript file that adds `Fluture` to the global
scope. Ideal for older browsers and code pens.
- [Fluture Script Minified][]: The same as above, but minified.
- [Fluture Module][]: An EcmaScript module with named exports. Ideal for Deno
or modern browsers.
- [Fluture Module Minified][]: A minified EcmaScript module without TypeScript
typings. Not recommended for Deno.
[Fluture Script]: https://cdn.jsdelivr.net/gh/fluture-js/Fluture@14.0.0/dist/bundle.js
[Fluture Script Minified]: https://cdn.jsdelivr.net/gh/fluture-js/Fluture@14.0.0/dist/bundle.min.js
[Fluture Module]: https://cdn.jsdelivr.net/gh/fluture-js/Fluture@14.0.0/dist/module.js
[Fluture Module Minified]: https://cdn.jsdelivr.net/gh/fluture-js/Fluture@14.0.0/dist/module.min.js
## Usage
### EcmaScript Module
Fluture is written as modular JavaScript.
- On Node 12 and up, Fluture can be loaded directly with `import 'fluture'`.
- On some older (minor) Node versions, you may need to import from
`'fluture/index.js'` instead, and/or pass `--experimental-modules` to `node`.
- On Node versions below 12, the [esm loader][esm] can be used. Alternatively,
there is a [CommonJS Module](#commonjs-module) available.
- Modern browsers can run Fluture directly. If you'd like to try this out,
I recommend installing Fluture with [Pika][] or [Snowpack][]. You can also
try the [bundled module](#bundled-from-a-cdn) to avoid a package manager.
- For older browsers, use a bundler such as [Rollup][] or WebPack. Besides the
module system, Fluture uses purely ES5-compatible syntax, so the source does
not have to be transpiled after bundling. Alternatively, there is a
[CommonJS Module](#commonjs-module) available.
```js
import {readFile} from 'fs'
import {node, encase, chain, map, fork} from 'fluture'
const getPackageName = file => (
node (done => { readFile (file, 'utf8', done) })
.pipe (chain (encase (JSON.parse)))
.pipe (map (x => x.name))
)
getPackageName ('package.json')
.pipe (fork (console.error) (console.log))
```
### CommonJS Module
Although the Fluture source uses the EcmaScript module system,
the `main` file points to a CommonJS version of Fluture.
On older environments one or more of the following functions may need to be
polyfilled: [`Object.create`][JS:Object.create],
[`Object.assign`][JS:Object.assign] and [`Array.isArray`][JS:Array.isArray].
```js
const fs = require ('fs')
const Future = require ('fluture')
const getPackageName = function (file) {
return Future.node (function (done) { fs.readFile (file, 'utf8', done) })
.pipe (Future.chain (Future.encase (JSON.parse)))
.pipe (Future.map (function (x) { return x.name }))
}
getPackageName ('package.json')
.pipe (Future.fork (console.error) (console.log))
```
## Documentation
### Table of contents
<details open><summary>General</summary>
- [Installation instructions](#installation)
- [Usage instructions](#usage)
- [About the Fluture project](#butterfly)
- [On interoperability with other libraries](#interoperability)
- [How to read the type signatures](#type-signatures)
- [How cancellation works](#cancellation)
- [On stack safety](#stack-safety)
- [Debugging with Fluture](#debugging)
- [Casting Futures to String](#casting-futures-to-string)
- [Usage with Sanctuary](#sanctuary)
- [Using multiple versions of Fluture alongside each other](#incompatible-fluture-versions)
</details>
<details><summary>Creating new Futures</summary>
- [`Future`: Create a possibly cancellable Future](#future)
- [`resolve`: Create a resolved Future](#resolve)
- [`reject`: Create a rejected Future](#reject)
- [`after`: Create a Future that resolves after a timeout](#after)
- [`rejectAfter`: Create a Future that rejects after a timeout](#rejectafter)
- [`go`: Create a "coroutine" using a generator function](#go)
- [`attempt`: Create a Future using a possibly throwing function](#attempt)
- [`attemptP`: Create a Future using a Promise-returning function](#attemptp)
- [`node`: Create a Future using a Node-style callback](#node)
- [`encase`: Convert a possibly throwing function to a Future function](#encase)
- [`encaseP`: Convert a Promise-returning function to a Future function](#encasep)
</details>
<details><summary>Converting between Nodeback APIs and Futures</summary>
- [`node`: Create a Future using a Node-style callback](#node)
- [`done`: Consume a Future by providing a Nodeback](#done)
</details>
<details><summary>Converting between Promises and Futures</summary>
- [`attemptP`: Create a Future using a Promise-returning function](#attemptp)
- [`encaseP`: Convert a Promise-returning function to a Future function](#encasep)
- [`promise`: Convert a Future to a Promise](#promise)
</details>
<details><summary>Transforming and combining Futures</summary>
- [`pipe`: Apply a function to a Future in a fluent method chain](#pipe)
- [`map`: Synchronously process the success value in a Future](#map)
- [`bimap`: Synchronously process the success or failure value in a Future](#bimap)
- [`chain`: Asynchronously process the success value in a Future](#chain)
- [`bichain`: Asynchronously process the success or failure value in a Future](#bichain)
- [`swap`: Swap the success with the failure value](#swap)
- [`mapRej`: Synchronously process the failure value in a Future](#maprej)
- [`chainRej`: Asynchronously process the failure value in a Future](#chainrej)
- [`coalesce`: Coerce success and failure values into the same success value](#coalesce)
- [`ap`: Combine the success values of multiple Futures using a function](#ap)
- [`pap`: Combine the success values of multiple Futures in parallel using a function](#pap)
- [`and`: Logical *and* for Futures](#and)
- [`alt`: Logical *or* for Futures](#alt)
- [`lastly`: Run a Future after the previous settles](#lastly)
- [`race`: Race two Futures against each other](#race)
- [`both`: Await both success values from two Futures](#both)
- [`parallel`: Await all success values from many Futures](#parallel)
</details>
<details><summary>Consuming/forking Futures</summary>
- [`fork`: Standard way to run a Future and get at its result](#fork)
- [`forkCatch`: Fork with exception recovery](#forkcatch)
- [`value`: Shorter variant of `fork` for Futures sure to succeed](#value)
- [`done`: Nodeback style `fork`](#done)
- [`promise`: Convert a Future to a Promise](#promise)
</details>
<details><summary>Concurrency related utilities and data structures</summary>
- [`pap`: Combine the success values of multiple Futures in parallel using a function](#pap)
- [`race`: Race two Futures against each other](#race)
- [`both`: Await both success values from two Futures](#both)
- [`parallel`: Await all success values from many Futures](#parallel)
- [`ConcurrentFuture`: A separate data-type for doing algebraic concurrency](#concurrentfuture)
- [`alt`: Behaves like `race` on `ConcurrentFuture` instances](#alt)
</details>
<details><summary>Resource management</summary>
- [`hook`: Safely create and dispose resources](#hook)
- [`lastly`: Run a Future after the previous settles](#lastly)
</details>
<details><summary>Other utilities</summary>
- [`pipe`: Apply a function to a Future in a fluent method chain](#pipe)
- [`cache`: Cache a Future so that it can be forked multiple times](#cache)
- [`isFuture`: Determine whether a value is a Fluture compatible Future](#isfuture)
- [`never`: A Future that never settles](#never)
- [`debugMode`: Configure Fluture's debug mode](#debugmode)
- [`context`: The debugging context of a Future instance](#context)
</details>
### Butterfly
The name "Fluture" is a conjunction of "FL" (the acronym to [Fantasy Land][FL])
and "future". Fluture means butterfly in Romanian: A creature one might expect
to see in Fantasy Land.
Credit goes to Erik Fuente for styling the logo, and [WEAREREASONABLEPEOPLE][9]
for sponsoring the project.
### Interoperability
[<img src="https://raw.github.com/fantasyland/fantasy-land/master/logo.png" align="right" width="82" height="82" alt="Fantasy Land" />][FL]
* `Future` implements [Fantasy Land][FL] 1.0+ -compatible
`Alt`, `Bifunctor`, `Monad`, and `ChainRec`
(`of`, `ap`, `alt`, `map`, `bimap`, `chain`, `chainRec`).
* `Future.Par` implements [Fantasy Land 3][FL] -compatible
`Alternative` (`of`, `zero`, `map`, `ap`, `alt`).
* The Future and ConcurrentFuture representatives contain `@@type` properties
for [Sanctuary Type Identifiers][STI].
* The Future and ConcurrentFuture instances contain `@@show` properties for
[Sanctuary Show][SS].
### Type signatures
The various function signatures are provided in a small language referred to as
Hindley-Milner notation.
In summary, the syntax is as follows: `InputType -> OutputType`. Now,
because functions in Fluture are [curried][Guide:currying], the "output" of a
function is often *another function*. In Hindley-Milner that's simply written
as `InputType -> InputToSecondFunction -> OutputType` and so forth.
By convention, types starting with an upper-case letter are
[concrete types](#types). When they start with a lower-case letter they're
*type variables*. You can think of these type variables as generic types.
So `a -> b` denotes a function from generic type `a` to generic type `b`.
Finally, through so-called [*constraints*](#type-classes), type variables can
be forced to conform to an "interface" (or *Type Class* in functional jargon).
For example, `MyInterface a => a -> b`, denotes a function from generic type
`a` to generic type `b`, *where `a` must implement `MyInterface`*.
You can read in depth about [Hindley-Milner in JavaScript][Guide:HM] here.
#### Types
The concrete types you will encounter throughout this documentation:
- **Future** - Instances of Future provided by
[compatible versions](#incompatible-fluture-versions) of Fluture.
- **ConcurrentFuture** - Futures wrapped with ([`Future.Par`](#concurrentfuture)).
- **Promise a b** - Values which conform to the [Promises/A+ specification][7]
and have a rejection reason of type `a` and a resolution value of type `b`.
- **Nodeback a b** - A Node-style callback; A function of signature `(a | Nil, b) -> x`.
- **Pair a b** - An array with exactly two elements: `[a, b]`.
- **Iterator** - Objects with `next`-methods which conform to the [Iterator protocol][3].
- **Cancel** - The nullary [cancellation](#cancellation) functions returned from computations.
- **Throwing e a b** - A function from `a` to `b` that may throw an exception `e`.
- **List** - Fluture's internal linked-list structure: `{ head :: Any, tail :: List }`.
- **Context** - Fluture's internal debugging context object:
`{ tag :: String, name :: String, stack :: String }`.
#### Type classes
Some signatures contain [constrained type variables][Guide:constraints].
Generally, these constraints express that some value must conform to a
[Fantasy Land][FL]-specified interface.
- **Functor** - [Fantasy Land Functor][FL:functor] conformant values.
- **Bifunctor** - [Fantasy Land Bifunctor][FL:bifunctor] conformant values.
- **Chain** - [Fantasy Land Chain][FL:chain] conformant values.
- **Apply** - [Fantasy Land Apply][FL:apply] conformant values.
- **Alt** - [Fantasy Land Alt][FL:alt] conformant values.
### Cancellation
Cancellation is a system whereby running Futures get an opportunity to stop
what they're doing and release resources that they were holding, when the
consumer indicates it is no longer interested in the result.
To cancel a Future, it must be unsubscribed from. Most of the
[consumption functions](#consuming-futures) return an `unsubscribe` function.
Calling it signals that we are no longer interested in the result. After
calling `unsubscribe`, Fluture guarantees that our callbacks will not be
called; but more importantly: a cancellation signal is sent upstream.
The cancellation signal travels all the way back to the source (with the
exception of cached Futures - see [`cache`](#cache)), allowing all parties
along the way to clean up.
With the [`Future` constructor](#future), we can provide a custom cancellation
handler by returning it from the computation. Let's see what this looks like:
```js
// We use the Future constructor to create a Future instance.
const eventualAnswer = Future (function computeTheAnswer (rej, res) {
// We give the computer time to think about the answer, which is 42.
const timeoutId = setTimeout (res, 60000, 42)
// Here is how we handle cancellation. This signal is received when nobody
// is interested in the answer any more.
return function onCancel () {
// Clearing the timeout releases the resources we were holding.
clearTimeout (timeoutId)
}
})
// Now, let's fork our computation and wait for an answer. Forking gives us
// the unsubscribe function.
const unsubscribe = fork (log ('rejection')) (log ('resolution')) (eventualAnswer)
// After some time passes, we might not care about the answer any more.
// Calling unsubscribe will send a cancellation signal back to the source,
// and trigger the onCancel function.
unsubscribe ()
```
Many natural sources in Fluture have cancellation handlers of their own.
[`after`](#after), for example, does exactly what we've done just now: calling
`clearTimeout`.
Finally, Fluture unsubscribes from Futures that it forks *for us*, when it no
longer needs the result. For example, both Futures passed into [race](#race)
are forked, but once one of them produces a result, the other is unsubscribed
from, triggering cancellation. This means that generally, unsubscription and
cancellation is fully managed for us behind the scenes.
### Stack safety
Fluture interprets our transformations in a stack safe way.
This means that none of the following operations result in a
`RangeError: Maximum call stack size exceeded`:
```js
> const add1 = x => x + 1
> let m = resolve (1)
> for (let i = 0; i < 100000; i++) {
. m = map (add1) (m)
. }
> fork (log ('rejection')) (log ('resolution')) (m)
[resolution]: 100001
```
```js
> const m = (function recur (x) {
. const mx = resolve (x + 1)
. return x < 100000 ? chain (recur) (mx) : mx
. }(1))
> fork (log ('rejection')) (log ('resolution')) (m)
[resolution]: 100001
```
To learn more about memory and stack usage under different types of recursion,
see (or execute) [`scripts/test-mem`](scripts/test-mem).
### Debugging
First and foremost, Fluture type-checks all of its input and throws TypeErrors
when incorrect input is provided. The messages they carry are designed to
provide enough insight to figure out what went wrong.
Secondly, Fluture catches exceptions that are thrown asynchronously, and
exposes them to you in one of two ways:
1. By throwing an Error when it happens.
2. By calling your [exception handler](#forkcatch) with an Error.
The original exception isn't used because it might have been any value.
Instead, a regular JavaScript Error instance whose properties are based on the
original exception is created. Its properties are as follows:
- `name`: Always just `"Error"`.
- `message`: The original error message, or a message describing the value.
- `reason`: The original value that was caught by Fluture.
- `context`: A linked list of "context" objects. This is used to create the
`stack` property, and you generally don't need to look at it. If debug mode
is not enabled, the list is always empty.
- `stack`: The stack trace of the original exception if it had one, or the
Error's own stack trace otherwise. If debug mode (see below) is enabled,
additional stack traces from the steps leading up to the crash are included.
- `future`: The instance of [`Future`](#future) that was being
[consumed](#consuming-futures) when the exception happened. Often
[printing it as a String](#casting-futures-to-string) can yield useful
information. You can also try to consume it in isolation to better identify
what's going wrong.
Finally, as mentioned, Fluture has a [debug mode](#debugmode) wherein
additional contextual information across multiple JavaScript ticks is
collected, included as an extended "async stack trace" on Errors, and
[exposed on Future instances](#context).
Debug mode can have a significant impact on performance, and uses up memory,
so I would advise against using it in production.
### Casting Futures to String
There are multiple ways to print a Future to String. Let's take a simple
computation as an example:
```js
const add = a => b => a + b;
const eventualAnswer = ap (resolve (22)) (map (add) (resolve (20)));
```
1. Casting it to String directly by calling `String(eventualAnswer)` or
`eventualAnswer.toString()` will yield an approximation of the code that
was used to create the Future. In this case:
```js
"ap (resolve (22)) (map (a => b => a + b) (resolve (20)))"
```
2. Casting it to String using `JSON.stringify(eventualAnswer, null, 2)` will
yield a kind of abstract syntax tree.
```json
{
"$": "fluture/Future@5",
"kind": "interpreter",
"type": "transform",
"args": [
{
"$": "fluture/Future@5",
"kind": "interpreter",
"type": "resolve",
"args": [
20
]
},
[
{
"$": "fluture/Future@5",
"kind": "transformation",
"type": "ap",
"args": [
{
"$": "fluture/Future@5",
"kind": "interpreter",
"type": "resolve",
"args": [
22
]
}
]
},
{
"$": "fluture/Future@5",
"kind": "transformation",
"type": "map",
"args": [
null
]
}
]
]
}
```
### Sanctuary
When using this module with [Sanctuary Def][$] (and [Sanctuary][S] by
extension) one might run into the following issue:
```js
> import S from 'sanctuary'
> import {resolve} from 'fluture'
> S.I (resolve (1))
! TypeError: Since there is no type of which all the above values are members,
. the type-variable constraint has been violated.
```
This happens because Sanctuary Def needs to know about the types created by
Fluture to determine whether the type-variables are consistent.
To let Sanctuary know about these types, we can obtain the type definitions
from [`fluture-sanctuary-types`][FST] and pass them to [`S.create`][S:create]:
```js
> import sanctuary from 'sanctuary'
> import {env as flutureEnv} from 'fluture-sanctuary-types'
> import {resolve} from 'fluture'
> const S = sanctuary.create ({checkTypes: true, env: sanctuary.env.concat (flutureEnv)})
> fork (log ('rejection'))
. (log ('resolution'))
. (S.I (resolve (42)))
[resolution]: 42
```
### Incompatible Fluture Versions
Most versions of Fluture understand how to consume instances from most other
versions, even across Fluture's major releases. This allows for different
packages that depend on Fluture to interact.
However, sometimes it's unavoidable that a newer version of Fluture is released
that can no longer understand older versions, and vice-versa. This only ever
happens on a major release, and will be mentioned in the breaking change log.
When two incompatible versions of Fluture meet instances, they do their best to
issue a clear error message about it.
When this happens, you need to manually convert the older instance to a newer
instance of Future. When [`isFuture`](#isfuture) returns `false`, a conversion
is necessary. You can also apply this trick if the Future comes from another
library similar to Fluture.
```js
const NoFuture = require ('incompatible-future')
const incompatible = NoFuture.of ('Hello')
const compatible = Future ((rej, res) => {
return NoFuture.fork (rej) (res) (incompatible)
})
both (compatible) (resolve ('world'))
```
### Creating Futures
#### Future
```hs
Future :: ((a -> Undefined, b -> Undefined) -> Cancel) -> Future a b
```
Creates a Future with the given computation. A computation is a function which
takes two callbacks. Both are continuations for the computation. The first is
`reject`, commonly abbreviated to `rej`; The second is `resolve`, or `res`.
When the computation is finished (possibly asynchronously) it may call the
appropriate continuation with a failure or success value.
Additionally, the computation must return a nullary function containing
cancellation logic. See [Cancellation](#cancellation).
If you find that there is no way to cancel your computation, you can return a
`noop` function as a cancellation function. However, at this point there is
usually a more fitting way to [create that Future](#creating-futures)
(like for example via [`node`](#node)).
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (Future (function computation (reject, resolve) {
. const t = setTimeout (resolve, 20, 42)
. return () => clearTimeout (t)
. }))
[resolution]: 42
```
#### resolve
```hs
resolve :: b -> Future a b
```
Creates a Future which immediately resolves with the given value.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (resolve (42))
[answer]: 42
```
#### reject
```hs
reject :: a -> Future a b
```
Creates a Future which immediately rejects with the given value.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (reject ('It broke!'))
[rejection]: "It broke!"
```
#### after
```hs
after :: Number -> b -> Future a b
```
Creates a Future which resolves with the given value after
the given number of milliseconds.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (after (20) (42))
[resolution]: 42
```
#### rejectAfter
```hs
rejectAfter :: Number -> a -> Future a b
```
Creates a Future which rejects with the given reason after the given number of
milliseconds.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (rejectAfter (20) ('It broke!'))
[rejection]: "It broke!"
```
#### go
```hs
go :: (() -> Iterator) -> Future a b
```
A way to do `async`/`await` with Futures, similar to Promise Coroutines or
Haskell Do-notation.
Takes a function which returns an [Iterator](#types), commonly a
generator-function, and chains every produced Future over the previous.
```js
> fork (log ('rejection')) (log ('resolution')) (go (function*() {
. const thing = yield after (20) ('world')
. const message = yield after (20) ('Hello ' + thing)
. return message + '!'
. }))
[resolution]: "Hello world!"
```
A rejected Future short-circuits the whole coroutine.
```js
> fork (log ('rejection')) (log ('resolution')) (go (function*() {
. const thing = yield reject ('It broke!')
. const message = yield after (20) ('Hello ' + thing)
. return message + '!'
. }))
[rejection]: "It broke!"
```
To handle rejections *inside* the coroutine, we need to [`coalesce`](#coalesce)
the error into our control domain.
I recommend using coalesce with an [`Either`][S:Either].
```js
> const control = coalesce (S.Left) (S.Right)
> fork (log ('rejection')) (log ('resolution')) (go (function*() {
. const thing = yield control (reject ('It broke!'))
. return S.either (x => `Oh no! ${x}`)
. (x => `Yippee! ${x}`)
. (thing)
. }))
[resolution]: "Oh no! It broke!"
```
#### attempt
```hs
attempt :: Throwing e Undefined r -> Future e r
```
Creates a Future which resolves with the result of calling the given function,
or rejects with the error thrown by the given function.
Short for [`encase (f) (undefined)`](#encase).
```js
> const data = {foo: 'bar'}
> fork (log ('rejection'))
. (log ('resolution'))
. (attempt (() => data.foo.bar.baz))
[rejection]: new TypeError ("Cannot read property 'baz' of undefined")
```
#### attemptP
```hs
attemptP :: (Undefined -> Promise a b) -> Future a b
```
Create a Future which when forked spawns a Promise using the given function and
resolves with its resolution value, or rejects with its rejection reason.
Short for [`encaseP (f) (undefined)`](#encasep).
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (attemptP (() => Promise.resolve (42)))
[resolution]: 42
```
#### node
```hs
node :: (Nodeback e r -> x) -> Future e r
```
Creates a Future which rejects with the first argument given to the function,
or resolves with the second if the first is not present.
Note that this function **does not support cancellation**.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (node (done => done (null, 42)))
[resolution]: 42
```
#### encase
```hs
encase :: Throwing e a r -> a -> Future e r
```
Takes a function and a value, and returns a Future which when forked calls the
function with the value and resolves with the result. If the function throws
an exception, it is caught and the Future will reject with the exception.
Applying `encase` with a function `f` creates a "safe" version of `f`. Instead
of throwing exceptions, the encased version always returns a Future.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (encase (JSON.parse) ('{"foo" = "bar"}'))
[rejection]: new SyntaxError ('Unexpected token =')
```
#### encaseP
```hs
encaseP :: (a -> Promise e r) -> a -> Future e r
```
Turns Promise-returning functions into Future-returning functions.
Takes a function which returns a Promise, and a value, and returns a Future.
When forked, the Future calls the function with the value to produce the
Promise, and resolves with its resolution value, or rejects with its rejection
reason.
```js
> encaseP (fetch) ('https://api.github.com/users/Avaq')
. .pipe (chain (encaseP (res => res.json ())))
. .pipe (map (user => user.name))
. .pipe (fork (log ('rejection')) (log ('resolution')))
[resolution]: "Aldwin Vlasblom"
```
### Transforming Futures
#### map
```hs
map :: Functor m => (a -> b) -> m a -> m b
```
Transforms the resolution value inside the Future or [Functor][FL:functor],
and returns a Future or Functor with the new value. The transformation is only
applied to the resolution branch: if the Future is rejected, the transformation
is ignored.
See also [`chain`](#chain) and [`mapRej`](#maprej).
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (map (x => x + 1) (resolve (41)))
[resolution]: 42
```
For comparison, an approximation with Promises is:
```js
> Promise.resolve (41)
. .then (x => x + 1)
. .then (log ('resolution'), log ('rejection'))
[resolution]: 42
```
#### bimap
```hs
bimap :: Bifunctor m => (a -> c) -> (b -> d) -> m a b -> m c d
```
Maps the left function over the rejection reason, or the right function over
the resolution value, depending on which is present. Can be used on any
[Bifunctor][FL:bifunctor].
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (bimap (x => x + '!') (x => x + 1) (resolve (41)))
[resolution]: 42
> fork (log ('rejection'))
. (log ('resolution'))
. (bimap (x => x + '!') (x => x + 1) (reject ('It broke!')))
[rejection]: "It broke!!"
```
For comparison, an approximation with Promises is:
```js
> Promise.resolve (41)
. .then (x => x + 1, x => Promise.reject (x + '!'))
. .then (log ('resolution'), log ('rejection'))
[resolution]: 42
> Promise.reject ('It broke!')
. .then (x => x + 1, x => Promise.reject (x + '!'))
. .then (log ('resolution'), log ('rejection'))
[rejection]: "It broke!!"
```
#### chain
```hs
chain :: Chain m => (a -> m b) -> m a -> m b
```
Sequence a new Future or [Chain][FL:chain] using the resolution value from
another. Similarly to [`map`](#map), `chain` expects a function. But instead
of returning the new *value*, chain expects a Future (or instance of the same
Chain) to be returned.
The transformation is only applied to the resolution branch: if the Future is
rejected, the transformation is ignored.
See also [`chainRej`](#chainrej).
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (chain (x => resolve (x + 1)) (resolve (41)))
[resolution]: 42
```
For comparison, an approximation with Promises is:
```js
> Promise.resolve (41)
. .then (x => Promise.resolve (x + 1))
. .then (log ('resolution'), log ('rejection'))
[resolution]: 42
```
#### bichain
```hs
bichain :: (a -> Future c d) -> (b -> Future c d) -> Future a b -> Future c d
```
Sequence a new Future using either the resolution or the rejection value from
another. Similarly to [`bimap`](#bimap), `bichain` expects two functions. But
instead of returning the new *value*, bichain expects Futures to be returned.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (bichain (resolve) (x => resolve (x + 1)) (resolve (41)))
[resolution]: 42
> fork (log ('rejection'))
. (log ('resolution'))
. (bichain (x => resolve (x + 1)) (resolve) (reject (41)))
[resolution]: 42
```
For comparison, an approximation with Promises is:
```js
> Promise.resolve (41)
. .then (x => Promise.resolve (x + 1), Promise.resolve)
. .then (log ('resolution'), log ('rejection'))
[resolution]: 42
> Promise.reject (41)
. .then (Promise.resolve, x => Promise.resolve (x + 1))
. .then (log ('resolution'), log ('rejection'))
[resolution]: 42
```
#### swap
```hs
swap :: Future a b -> Future b a
```
Swap the rejection and resolution branches.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (swap (resolve (42)))
[rejection]: 42
> fork (log ('rejection'))
. (log ('resolution'))
. (swap (reject (42)))
[resolution]: 42
```
#### mapRej
```hs
mapRej :: (a -> c) -> Future a b -> Future c b
```
Map over the **rejection** reason of the Future. This is like [`map`](#map),
but for the rejection branch.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (mapRej (s => `Oh no! ${s}`) (reject ('It broke!')))
[rejection]: "Oh no! It broke!"
```
For comparison, an approximation with Promises is:
```js
> Promise.reject ('It broke!')
. .then (null, s => Promise.reject (`Oh no! ${s}`))
. .then (log ('resolution'), log ('rejection'))
[rejection]: "Oh no! It broke!"
```
#### chainRej
```hs
chainRej :: (a -> Future c b) -> Future a b -> Future c b
```
Chain over the **rejection** reason of the Future. This is like
[`chain`](#chain), but for the rejection branch.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (chainRej (s => resolve (`${s} But it's all good.`)) (reject ('It broke!')))
[resolution]: "It broke! But it's all good."
```
For comparison, an approximation with Promises is:
```js
> Promise.reject ('It broke!')
. .then (null, s => `${s} But it's all good.`)
. .then (log ('resolution'), log ('rejection'))
[resolution]: "It broke! But it's all good."
```
#### coalesce
```hs
coalesce :: (a -> c) -> (b -> c) -> Future a b -> Future d c
```
Applies the left function to the rejection value, or the right function to the
resolution value, depending on which is present, and resolves with the result.
This provides a convenient means to ensure a Future is always resolved. It can
be used with other type constructors, like [`S.Either`][S:Either], to maintain
a representation of failure.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (coalesce (S.Left) (S.Right) (resolve ('hello'))
[resolution]: Right ("hello")
> fork (log ('rejection'))
. (log ('resolution'))
. (coalesce (S.Left) (S.Right) (reject ('It broke!'))
[resolution]: Left ("It broke!")
```
For comparison, an approximation with Promises is:
```js
> Promise.resolve ('hello')
. .then (S.Right, S.Left)
. .then (log ('resolution'), log ('rejection'))
[resolution]: Right ("hello")
> Promise.reject ('It broke!')
. .then (S.Right, S.Left)
. .then (log ('resolution'), log ('rejection'))
[resolution]: Left ("It broke!")
```
### Combining Futures
#### ap
```hs
ap :: Apply m => m a -> m (a -> b) -> m b
```
Applies the function contained in the right-hand Future or [Apply][FL:apply]
to the value contained in the left-hand Future or Apply. This process can be
repeated to gradually fill out multiple function arguments of a curried
function, as shown below.
Note that the Futures will be executed in sequence - not in parallel\* -
because of the Monadic nature of Futures. The execution order is, as
specified by Fantasy Land, `m (a -> b)` first followed by `m a`.
So that's *right before left*.
\* Have a look at [`pap`](#pap) for an `ap` function that runs its arguments
in parallel. If you must use `ap` (because you're creating a generalized
function), but still want Futures passed into it to run in parallel, then
you could use [ConcurrentFuture](#concurrentfuture) instead.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (ap (resolve (7)) (ap (resolve (49)) (resolve (x => y => x - y))))
[resolution]: 42
```
#### pap
```hs
pap :: Future a b -> Future a (b -> c) -> Future a c
```
Has the same signature and function as [`ap`](#ap), but runs the two Futures
given to it in parallel. See also [ConcurrentFuture](#concurrentfuture) for a
more general way to achieve this.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (pap (resolve (7)) (pap (resolve (49)) (resolve (x => y => x - y))))
[resolution]: 42
```
#### alt
```hs
alt :: Alt f => f a -> f a -> f a
```
Select one of two [Alts](#types).
Behaves like logical *or* on [`Future`](#future) instances, returning a new
Future which either resolves with the first resolution value, or rejects with
the last rejection reason. We can use it if we want a computation to run only
if another has failed.
Note that the Futures will be executed in sequence - not in parallel\* -
because of the Monadic nature of Futures. The *right* Future is evaluated
before the *left* Future.
See also [`and`](#and) and [`lastly`](#lastly).
\* If you'd like to use a parallel implementation of `alt`, you could simply
use [`race`](#race). Alternatively you could wrap your Future instances
with [`Par`](#concurrentfuture) before passing them to `alt`.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (alt (resolve ('left')) (resolve ('right')))
[resolution]: "right"
> fork (log ('rejection'))
. (log ('resolution'))
. (alt (resolve ('left')) (reject ('It broke!')))
[resolution]: "left"
```
#### and
```hs
and :: Future a c -> Future a b -> Future a c
```
Logical *and* for Futures.
Returns a new Future which either rejects with the first rejection reason, or
resolves with the last resolution value once and if both Futures resolve. We
can use it if we want a computation to run only after another has succeeded.
The *right* Future is evaluated before the *left* Future.
See also [`alt`](#alt) and [`lastly`](#lastly).
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (and (resolve ('left')) (resolve ('right')))
[resolution]: "left"
> fork (log ('rejection'))
. (log ('resolution'))
. (and (resolve ('left')) (reject ('It broke!')))
[rejection]: "It broke!"
```
#### lastly
```hs
lastly :: Future a c -> Future a b -> Future a b
```
Run a second Future after the first settles (successfully or unsuccessfully).
Rejects with the rejection reason from the first or second Future, or resolves
with the resolution value from the first Future. This can be used to run a
computation after another settles, successfully or unsuccessfully.
If you're looking to clean up resources after running a computation which
acquires them, you should use [`hook`](#hook), which has many more fail-safes
in place.
See also [`and`](#and) and [`alt`](#alt).
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (lastly (encase (log ('lastly')) ('All done!')) (resolve (42)))
[lastly]: "All done!"
[resolution]: 42
```
### Consuming Futures
#### fork
```hs
fork :: (a -> Any) -> (b -> Any) -> Future a b -> Cancel
```
Execute the computation represented by a Future, passing `reject` and `resolve`
callbacks to continue once there is a result.
This function is called `fork` because it literally represents a fork in our
program: a point where a single code-path splits in two. It is recommended to
keep the number of calls to `fork` at a minimum for this reason. The more
forks, the higher the code complexity.
Generally, one only needs to call `fork` in a single place in the entire
program.
After we `fork` a Future, the computation will start running. If the program
decides halfway through that it's no longer interested in the result of the
computation, it can call the `unsubscribe` function returned by `fork`. See
[Cancellation](#cancellation).
If an exception was encountered during the computation, it will be re-thrown
by `fork` and likely not be catchable. You can handle it using
`process.on('uncaughtException')` in Node, or use [`forkCatch`](#forkcatch).
Almost all code examples in Fluture use `fork` to run the computation. There
are some variations on `fork` that serve different purposes below.
#### forkCatch
```hs
forkCatch :: (Error -> Any) -> (a -> Any) -> (b -> Any) -> Future a b -> Cancel
```
An advanced version of [fork](#fork) that allows us to react to a fatal error
in a custom way. Fatal errors occur when unexpected exceptions are thrown, when
the Fluture API is used incorrectly, or when resources couldn't be disposed.
The exception handler will always be called with an instance of `Error`,
independent of what caused the crash.
**Using this function is a trade-off;**
Generally it's best to let a program crash and restart when an a fatal error
occurs. Restarting is the surest way to restore the memory that was allocated
by the program to an expected state.
By using `forkCatch`, we can keep our program alive after a fatal error, which
can be very beneficial when the program is being used by multiple clients.
However, since fatal errors might indicate that something, somewhere has
entered an invalid state, it's probably still best to restart our program upon
encountering one.
See [Debugging](#debugging) for information about the Error object that is
passed to your exception handler.
```js
> forkCatch (log ('fatal error'))
. (log ('rejection'))
. (log ('resolution'))
. (map (x => x.foo) (resolve (null)))
[fatal error]: new Error ("Cannot read property 'foo' of null")
```
#### value
```hs
value :: (b -> Any) -> Future a b -> Cancel
```
Like [`fork`](#fork) but for the resolution branch only. Only use this function
if you are sure the Future is going to be resolved, for example; after using
[`coalesce`](#coalesce). If the Future rejects, `value` will throw an Error.
As with [`fork`](#fork), `value` returns an `unsubscribe` function. See
[Cancellation](#cancellation).
```js
> value (log ('resolution')) (resolve (42))
[resolution]: 42
```
#### done
```hs
done :: Nodeback a b -> Future a b -> Cancel
```
Run the Future using a [Nodeback](#types) as the continuation.
This is like [`fork`](#fork), but instead of taking two unary functions, it
takes a single binary function.
As with [`fork`](#fork), `done` returns an `unsubscribe` function. See
[Cancellation](#cancellation).
```js
> done ((err, val) => log ('resolution') (val)) (resolve (42))
[resolution]: 42
```
#### promise
```hs
promise :: Future Error a -> Promise Error a
```
Run the Future and get a Promise to represent its continuation.
Returns a Promise which resolves with the resolution value, or rejects with
the rejection reason of the Future.
If an exception was encountered during the computation, the promise will reject
with it. I recommend using [`coalesce`](#coalesce) before `promise` to ensure
that exceptions and rejections are not mixed into the Promise rejection branch.
Cancellation capabilities are lost when using `promise` to consume the Future.
```js
> promise (resolve (42)) .then (log ('resolution'))
[resolution]: 42
> promise (reject ('failure')) .then (log ('resolution'), log ('rejection'))
[rejection]: "failure"
```
### Parallelism
#### race
```hs
race :: Future a b -> Future a b -> Future a b
```
Race two Futures against each other. Creates a new Future which resolves or
rejects with the resolution or rejection value of the first Future to settle.
When one Future settles, the other gets cancelled automatically.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (race (after (15) ('left')) (after (30) ('right')))
[resolution]: "left"
```
#### both
```hs
both :: Future a b -> Future a c -> Future a (Pair b c)
```
Run two Futures in parallel and get a [`Pair`](#types) of the results. When
either Future rejects, the other Future will be cancelled and the resulting
Future will reject.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (both (after (15) ('left')) (after (30) ('right')))
[resolution]: ["left", "right"]
```
#### parallel
```hs
parallel :: PositiveInteger -> Array (Future a b) -> Future a (Array b)
```
Creates a Future which when forked runs all Futures in the given Array in
parallel, ensuring no more than `limit` Futures are running at once.
In the following example, we're running up to 5 Futures in parallel. Every
Future takes about 20ms to settle, which means the result should appear after
about 40ms.
If we use `1` for the limit, the Futures would run in sequence, causing the
result to appear only after 200ms.
We can also use `Infinity` as the limit. This would create a function similar
to `Promise.all`, which always runs all Futures in parallel. This can easily
cause the computation to consume too many resources, however, so I would
advise using a number roughly equal to maximum size of Array you think your
program should handle.
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (parallel (5) (Array.from (Array (10) .keys ()) .map (after (20))))
[resolution]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```
When one Future rejects, all currently running Futures will be cancelled and
the resulting Future will reject. If you want to settle all Futures, even if
some may fail, you can use `parallel` in combination with
[coalesce](#coalesce).
```js
> fork (log ('rejection'))
. (log ('resolution'))
. (parallel (2) ([resolve (42), reject ('It broke!')]
. .map (coalesce (S.Left) (S.Right))))
[resolution]: [Right (42), Left ("It broke!")]
```
#### ConcurrentFuture
The `ConcurrentFuture` type is very similar to the `Future` type, except that
it has *parallel* semantics where `Future` has *sequential* semantics.
These sematics are most notable in the implementation of Applicative for
`ConcurrentFuture`. When using [`ap`](#ap) on two ConcurrentFutures, they
run parallely, whereas regular `Future` instances would've run sequentially.
This means that `ConcurrentFuture` cannot be a Monad, which is why we have
it as a separate type.
The implementation of Alternative on `ConcurrentFuture` has parallel semantics
as well. Whereas [`alt`](#alt) on regular Futures uses the failure effect to
determine a winner, on ConcurrentFutures *timing* is used, and the winner will
be whichever ConcurrentFuture settled first.
The idea is that we can switch back and forth between `Future` and
`ConcurrentFuture`, using [`Par`](#par) and [`seq`](#seq), to get sequential or
concurrent behaviour respectively. It's a useful type to pass to abstractions
that don't know about Future-specific functions like [`parallel`](#parallel) or
[`race`](#race), but *do* know how to operate on Apply and Alternative.
```js
//Some dummy values
const x = 41;
const f = a => a + 1;
//The following two are equal ways to construct a ConcurrentFuture
const parx = S.of (Par) (x)
const parf = Par (S.of (Future) (f))
//We can make use of parallel apply
value (log ('resolution')) (seq (ap (parx) (parf)))
[resolution]: 42
//Concurrent sequencing
value (log ('resolution')) (seq (S.sequence (Par) ([parx, parx, parx])))
[resolution]: [41, 41, 41]
//And concurrent alt
value (log ('resolution')) (alt (after (15) ('left')) (after (30) ('right')))
[resolution]: "left"
```
##### Par
```hs
Par :: Future a b -> ConcurrentFuture a b
```
Converts a Future to a ConcurrentFuture.
##### seq
Converts a ConcurrentFuture to a Future.
```hs
seq :: ConcurrentFuture a b -> Future a b
```
### Resource management
Functions listed under this category allow for more fine-grained control over
the flow of acquired values.
#### hook
```hs
hook :: Future a b -> (b -> Future c d) -> (b -> Future a e) -> Future a e
```
Combines resource acquisition, consumption, and disposal in such a way that you
can be sure that a resource will always be disposed if it was acquired, even if
an exception is thrown during consumption; Sometimes referred to as bracketing.
The signature is like `hook (acquire, dispose, consume)`, where:
- `acquire` is a Future which might create connections, open files, etc.
- `dispose` is a function that takes the result from `acquire` and should be
used to clean up (close connections etc). The Future it returns must
resolve, and its resolution value is ignored. If it rejects, a fatal error
is raised which can only be handled with [`forkCatch`](#forkcatch).
- `consume` is another Function takes the result from `acquire`, and may be
used to perform any arbitrary computations using the resource.
Typically, you'd want to partially apply this function with the first two
arguments (acquisition and disposal), as shown in the example.
```js
> import {open, read, close} from 'fs'
> const withFile = hook (node (done => open ('package.json', 'r', done)))
. (fd => node (done => close (fd, done)))
> fork (log ('rejection'))
. (log ('resolution'))
. (withFile (fd => node (done => (
. read (fd, Buffer.alloc (1), 0, 1, null, (e, _, x) => done (e, x)))
. )))
[resolution]: <Buffer 7b>
```
When a hooked Future is cancelled while acquiring its resource, nothing else
will happen. When it's cancelled after acquistion completes, however, the
disposal will still run, and if it fails, an exception will be thrown.
If you have multiple resources that you'd like to consume all at once, you can
use [Fluture Hooks](https://github.com/fluture-js/fluture-hooks) to combine
multiple hooks into one.
### Utility functions
#### pipe
```hs
Future.prototype.pipe :: Future a b ~> (Future a b -> c) -> c
```
A method available on all Futures to allow arbitrary functions over Futures to
be included in a fluent-style method chain.
You can think of this as a fallback for the [ESNext pipe operator (`|>`)][2].
```js
> resolve (x => y => x * y)
. .pipe (ap (after (20) (Math.PI)))
. .pipe (ap (after (20) (13.37)))
. .pipe (map (Math.round))
. .pipe (fork (log ('rejection')) (log ('resolution')))
[resolution]: 42
```
#### cache
```hs
cache :: Future a b -> Future a b
```
Returns a Future which caches the resolution value or rejection reason of the
given Future so that whenever it's forked, it can load the value from cache
rather than re-executing the underlying computation.
This essentially turns a unicast Future into a multicast Future, allowing
multiple consumers to subscribe to the same result. The underlying computation
is never [cancelled](#cancellation) unless *all* consumers unsubscribe before
it completes.
**There is a glaring drawback to using `cache`**, which is that returned
Futures are no longer referentially transparent, making reasoning about them
more difficult and refactoring code that uses them harder.
```js
> import {readFile} from 'fs'
> const eventualPackageName = (
. node (done => readFile ('package.json', 'utf8', done))
. .pipe (chain (encase (JSON.parse)))
. .pipe (chain (encase (x => x.name)))
. .pipe (map (data => {
. log ('debug') ('Read, parsed, and traversed the package data')
. return data
. }))
. )
> fork (log ('rejection')) (log ('resolution')) (eventualPackageName)
[debug]: "Read, parsed, and traversed the package data"
[resolution]: "Fluture"
> fork (log ('rejection')) (log ('resolution')) (eventualPackageName)
[debug]: "Read, parsed, and traversed the package data"
[resolution]: "Fluture"
> const eventualCachedPackageName = cache (eventualPackageName)
> fork (log ('rejection')) (log ('resolution')) (eventualCachedPackageName)
[debug]: "Read, parsed, and traversed the package data"
[resolution]: "Fluture"
> fork (log ('rejection')) (log ('resolution')) (eventualCachedPackageName)
[resolution]: "Fluture"
```
#### isFuture
```hs
isFuture :: a -> Boolean
```
Returns true for [Futures](#types) and false for everything else. This function
(and [`S.is`][S:is]) also return `true` for instances of Future that were
created within other contexts. It is therefore recommended to use this over
`instanceof`, unless your intent is to explicitly check for Futures created
using the exact `Future` constructor you're testing against.
```js
> isFuture (resolve (42))
true
> isFuture (42)
false
```
#### never
```hs
never :: Future a b
```
A Future that never settles. Can be useful as an initial value when reducing
with [`race`](#race), for example.
#### isNever
```hs
isNever :: a -> Boolean
```
Returns `true` if the given input is a `never`.
#### extractLeft
```hs
extractLeft :: Future a b -> Array a
```
Returns an array whose only element is the rejection reason of the Future.
In many cases it will be impossible to extract this value; In those cases, the
array will be empty. This function is meant to be used for type introspection:
it is **not** the correct way to [consume a Future](#consuming-futures).
#### extractRight
```hs
extractRight :: Future a b -> Array b
```
Returns an array whose only element is the resolution value of the Future.
In many cases it will be impossible to extract this value; In those cases, the
array will be empty. This function is meant to be used for type introspection:
it is **not** the correct way to [consume a Future](#consuming-futures).
#### debugMode
```hs
debugMode :: Boolean -> Undefined
```
Enable or disable Fluture's debug mode. Debug mode is disabled by default.
Pass `true` to enable, or `false` to disable.
```js
debugMode (true)
```
For more information, see [Debugging](#debugging) and [Context](#context).
#### context
```hs
Future.prototype.context :: Future a b ~> List Context
```
A linked list of debugging contexts made available on every instance of
`Future`. When [debug mode](#debugmode) is disabled, the list is always empty.
The context objects have `stack` properties which contain snapshots of the
stacktraces leading up to the creation of the `Future` instance. They are used
by Fluture to generate contextual stack traces.
## License
[MIT licensed](LICENSE)
<!-- References -->
[wiki:similar]: https://github.com/fluture-js/Fluture/wiki/Comparison-of-Future-Implementations
[wiki:promises]: https://github.com/fluture-js/Fluture/wiki/Comparison-to-Promises
[FL]: https://github.com/fantasyland/fantasy-land
[FL:alt]: https://github.com/fantasyland/fantasy-land#alt
[FL:alternative]: https://github.com/fantasyland/fantasy-land#alternative
[FL:functor]: https://github.com/fantasyland/fantasy-land#functor
[FL:chain]: https://github.com/fantasyland/fantasy-land#chain
[FL:apply]: https://github.com/fantasyland/fantasy-land#apply
[FL:bifunctor]: https://github.com/fantasyland/fantasy-land#bifunctor
[FL:chainrec]: https://github.com/fantasyland/fantasy-land#chainrec
[JS:Object.create]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
[JS:Object.assign]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
[JS:Array.isArray]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
[S]: https://sanctuary.js.org/
[S:Either]: https://sanctuary.js.org/#either-type
[S:is]: https://sanctuary.js.org/#is
[S:create]: https://sanctuary.js.org/#create
[S:join]: https://sanctuary.js.org/#join
[SS]: https://github.com/sanctuary-js/sanctuary-show
[STI]: https://github.com/sanctuary-js/sanctuary-type-identifiers
[FST]: https://github.com/fluture-js/fluture-sanctuary-types
[$]: https://github.com/sanctuary-js/sanctuary-def
[Rollup]: https://rollupjs.org/
[Pika]: https://www.pikapkg.com/
[Snowpack]: https://www.snowpack.dev/
[esm]: https://github.com/standard-things/esm
[Deno]: https://deno.land/
[Guide:HM]: https://mostly-adequate.gitbook.io/mostly-adequate-guide/ch07
[Guide:constraints]: https://mostly-adequate.gitbook.io/mostly-adequate-guide/ch07#constraints
[Guide:currying]: https://mostly-adequate.gitbook.io/mostly-adequate-guide/ch04
[1]: https://en.wikipedia.org/wiki/Continuation-passing_style
[2]: https://github.com/tc39/proposal-pipeline-operator
[3]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#iterator
[5]: https://vimeo.com/106008027
[7]: https://promisesaplus.com/
[9]: https://wearereasonablepeople.nl/
[10]: https://dev.to/avaq/fluture-a-functional-alternative-to-promises-21b
================================================
FILE: bench/.eslintrc.json
================================================
{
"root": true,
"extends": ["warp/node", "warp/es6"],
"rules": {
"max-len": [0]
}
}
================================================
FILE: bench/.npmrc
================================================
package-lock=false
save=false
================================================
FILE: bench/README.md
================================================
# Benchmarks
## Running
* Install node modules required for the benchmark you wish to run
* Use `npm run bench -- --help` for options
For example, let's say you like to know how the performance of `parallel`
compares to what it was at version 5.x.x:
```console
$ (cd bench && npm install fluture@5.x.x)
$ npm run bench -- --benchmark fluture --match *.parallel.*
```
================================================
FILE: bench/fluture.js
================================================
/* global setImmediate */
import bench from 'sanctuary-benchmark';
import Old from 'fluture';
import * as New from '../index.js';
const config = {leftHeader: 'Old', rightHeader: 'New'};
const noop = () => {};
const compose = (f, g) => x => f(g(x));
const run = m => m.constructor.fork(noop)(noop)(m);
const plus1 = x => x + 1;
const arr = (T, length) => Array.from({length}, (_, i) => T.resolve(i));
const fast = (T, x) => T((rej, res) => void setImmediate(res, x));
const slow = (T, x) => T.after(1)(x);
export default bench(Old, New, config, {
'def.interpreter.Future': [
{}, ({Future}) => Future((rej, res) => res(1))
],
'def.interpreter.resolve': [
{}, ({resolve}) => resolve(1)
],
'def.interpreter.reject': [
{}, ({reject}) => reject(1)
],
'def.interpreter.after': [
{}, ({after}) => after(1)(1)
],
'def.interpreter.attempt': [
{}, ({attempt}) => attempt(noop)
],
'def.interpreter.cache': [
{}, ({resolve, cache}) => cache(resolve(1))
],
'def.interpreter.encase': [
{}, ({encase}) => encase(noop)(1)
],
'def.interpreter.encaseP': [
{}, ({encaseP}) => encaseP(noop)(1)
],
'def.interpreter.go': [
{}, ({go}) => go(noop)
],
'def.interpreter.hook': [
{}, ({resolve, hook}) => hook(resolve(1))(noop)(noop)
],
'def.interpreter.node': [
{}, ({node}) => node(done => done(null, 1))
],
'def.interpreter.parallel': [
{}, ({resolve, parallel}) => parallel(1)([resolve(1)])
],
'def.transformation.map': [
{}, ({resolve, map}) => map(plus1)(resolve(1))
],
'def.transformation.chain': [
{}, ({resolve, chain}) => chain(plus1)(resolve(1))
],
'run.interpreter.Future': [
{}, ({Future}) => run(Future((rej, res) => res(1)))
],
'run.interpreter.parallel.empty': [
{}, ({parallel}) => run(parallel(1)([]))
],
'run.interpreter.parallel.small.sequential': [
{}, ({Future, parallel}) => run(parallel(1)(arr(Future, 2)))
],
'run.interpreter.parallel.small.concurrent': [
{}, ({Future, parallel}) => run(parallel(2)(arr(Future, 2)))
],
'run.interpreter.parallel.big.sequential': [
{}, ({Future, parallel}) => run(parallel(1)(arr(Future, 100)))
],
'run.interpreter.parallel.big.concurrent': [
{}, ({Future, parallel}) => run(parallel(2)(arr(Future, 100)))
],
'run.interpreter.go': [
{}, ({go, resolve}) => run(go(function*(){
return (yield resolve(1)) + (yield resolve(2));
}))
],
'run.transformation.sync.map': [
{}, ({resolve, map}) => run(map(plus1)(resolve(1)))
],
'run.transformation.sync.swap.one': [
{}, ({resolve, swap}) => run(swap(resolve(42)))
],
'run.transformation.sync.swap.many': [
{}, ({resolve, swap}) => {
let m = resolve(1);
for(let i = 0; i < 1000; i++){ m = swap(m) }
run(m);
}
],
'run.transformation.sync.chain.one': [
{}, ({resolve, chain}) => run(chain(compose(resolve, plus1))(resolve(1)))
],
'run.transformation.sync.chain.many': [
{}, ({chain, resolve}) => {
const f = compose(resolve, plus1);
let m = resolve(1);
for(let i = 0; i < 1000; i++){ m = chain(f)(m) }
run(m);
}
],
'run.transformation.async.map': [
{defer: true}, ({Future, map, value}, [d]) => {
map(plus1)(fast(Future, 1)).pipe(value(() => d.resolve()));
}
],
'run.transformation.async.chain.one': [
{defer: true}, ({Future, chain, value}, [d]) => {
chain(x => fast(Future, plus1(x)))(fast(Future, 1))
.pipe(value(() => d.resolve()));
}
],
'run.transformation.async.chain.many': [
{defer: true}, ({Future, chain, value}, [d]) => {
const f = x => fast(Future, plus1(x));
let m = fast(Future, 1);
for(let i = 0; i < 100; i++){ m = chain(f)(m) }
m.pipe(value(() => d.resolve()));
}
],
'run.transformation.parallel.async.race.fast-vs-slow': [
{defer: true}, ({Future, race, value}, [d]) => {
const a = fast(Future, 1);
const b = slow(Future, 1);
race(a)(b).pipe(value(() => d.resolve()));
}
],
'run.transformation.parallel.async.race.slow-vs-fast': [
{defer: true}, ({Future, race, value}, [d]) => {
const a = slow(Future, 1);
const b = fast(Future, 1);
race(a)(b).pipe(value(() => d.resolve()));
}
],
'run.transformation.parallel.async.race.slow-vs-slow': [
{defer: true}, ({Future, race, value}, [d]) => {
const a = slow(Future, 1);
const b = slow(Future, 1);
race(a)(b).pipe(value(() => d.resolve()));
}
],
});
================================================
FILE: bench/folktale.js
================================================
import bench from 'sanctuary-benchmark';
import * as Future from '../index.js';
import folktale from 'folktale/concurrency/task/index.js';
const noop = () => {};
const plus1 = x => x + 1;
const repeat = (n, f) => x => Array.from({length: n}).reduce(x => f(x), x);
const map1000 = repeat(1000, Future.map(plus1));
const chain1000 = repeat(1000, Future.chain(plus1));
const createTask = x => folktale.task(resolver => resolver.resolve(x));
const createFuture = x => Future.Future((rej, res) => { res(x); return noop });
const consumeTask = m => m.run().listen({onCancelled: noop, onRejected: noop, onResolved: noop});
const consumeFuture = Future.fork(noop)(noop);
const config = {leftHeader: 'Folktale', rightHeader: 'Fluture'};
const left = {
create: createTask,
consume: consumeTask,
one: createTask(1),
mapped: map1000(createTask(1))
};
const right = {
create: createFuture,
consume: consumeFuture,
one: createFuture(1),
mapped: map1000(createFuture(1))
};
export default bench(left, right, config, {
'create.construct': [
{}, ({create}) => repeat(1000, create)(1)
],
'create.map': [
{}, ({one}) => map1000(one)
],
'create.chain': [
{}, ({one}) => chain1000(one)
],
'consume.noop': [
{}, ({one, consume}) => consume(one)
],
'consume.map.1': [
{}, ({one, consume}) => consume(Future.map(plus1)(one))
],
'consume.map.1000': [
{}, ({mapped, consume}) => consume(mapped)
],
'consume.chain': [
{}, ({create, consume, one}) => consume(Future.chain(x => create(x + 1))(one))
],
});
================================================
FILE: bench/package.json
================================================
{
"name": "fluture-benchmarks",
"type": "module",
"version": "1.0.0",
"description": "A package.json for the purpose of being able to install dependencies in here",
"author": "Aldwin Vlasblom <aldwin.vlasblom@gmail.com> (https://github.com/Avaq)",
"license": "MIT",
"private": true
}
================================================
FILE: bench/promise.js
================================================
import bench from 'sanctuary-benchmark';
import * as Future from '../index.js';
const plus1 = x => x + 1;
const repeat = (n, f, x) => Array.from({length: n}).reduce(x => f(x), x);
const Left = x => ({left: true, right: false, value: x});
const Right = x => ({left: false, right: true, value: x});
const config = {leftHeader: 'Promise', rightHeader: 'Fluture'};
const def = f => [
{defer: true},
(x, [d]) => f(x).then(() => d.resolve()),
(x, [d]) => Future.value(() => d.resolve())(f(x))
];
const PromiseInterop = {
resolve: x => Promise.resolve(x),
map: f => p => p.then(f),
chain: f => p => p.then(f),
coalesce: f => g => p => p.then(g, f),
race: a => b => Promise.race([a, b]),
after: n => x => new Promise(res => setTimeout(res, n, x))
};
export default bench(PromiseInterop, Future, config, {
'resolve': def(
({resolve}) => repeat(1000, resolve, 1)
),
'after': def(
({after}) => after(10)(1)
),
'map': def(
({map, resolve}) => repeat(1000, map(plus1), resolve(1))
),
'coalesce': def(
({coalesce, resolve}) => repeat(1000, coalesce(Left)(Right), resolve(1))
),
'chain.sync': def(
({chain, resolve}) => repeat(1000, chain(x => resolve(plus1(x))), resolve(1))
),
'chain.async': def(
({chain, after}) => repeat(5, chain(x => after(1)(plus1(x))), after(1)(1))
),
'race.sync': def(
({race, resolve}) => repeat(1000, race(resolve(2)), resolve(1))
),
'race.async': def(
({race, after}) => repeat(5, race(after(1)(2)), after(1)(1))
),
});
================================================
FILE: dist/bundle.js
================================================
/**
* Fluture bundled; version 14.0.0
*/
var Fluture = (function () {
'use strict';
function createCommonjsModule(fn) {
var module = { exports: {} };
return fn(module, module.exports), module.exports;
}
/*
@@@@@@@ @@@@@@@ @@
@@ @@ @@ @@ @@@
@@ @@@ @@ @@ @@ @@@ @@ @@ @@@@@@ @@ @@@ @@ @@@ @@@@
@@ @@ @@@ @@ @@ @@ @@@ @@ @@@ @@ @@@ @@@ @@ @@@ @@
@@ @@ @@@ @@ @@ @@ @@@ @@ @@@ @@ @@@ @@@ @@ @@@@@@@@
@@ @@ @@@ @@ @@ @@ @@@ @@ @@@ @@ @@@ @@@ @@ @@@
@@ @@@ @@@@@ @@ @@@ @@@@@ @@@ @@@ @@ @@@@@@ @@@@@
@@ @@ @@ @@
@@@@@@@ @@@@@@@ @@@@@ @@
*/
var sanctuaryTypeIdentifiers = createCommonjsModule(function (module) {
//. # sanctuary-type-identifiers
//.
//. A type is a set of values. Boolean, for example, is the type comprising
//. `true` and `false`. A value may be a member of multiple types (`42` is a
//. member of Number, PositiveNumber, Integer, and many other types).
//.
//. In certain situations it is useful to divide JavaScript values into
//. non-overlapping types. The language provides two constructs for this
//. purpose: the [`typeof`][1] operator and [`Object.prototype.toString`][2].
//. Each has pros and cons, but neither supports user-defined types.
//.
//. sanctuary-type-identifiers comprises:
//.
//. - an npm and browser -compatible package for deriving the
//. _type identifier_ of a JavaScript value; and
//. - a specification which authors may follow to specify type
//. identifiers for their types.
//.
//. ### Specification
//.
//. For a type to be compatible with the algorithm:
//.
//. - every member of the type MUST have a `@@type` property
//. (the _type identifier_); and
//.
//. - the type identifier MUST be a string primitive and SHOULD have
//. format `'<namespace>/<name>[@<version>]'`, where:
//.
//. - `<namespace>` MUST consist of one or more characters, and
//. SHOULD equal the name of the npm package which defines the
//. type (including [scope][3] where appropriate);
//.
//. - `<name>` MUST consist of one or more characters, and SHOULD
//. be the unique name of the type; and
//.
//. - `<version>` MUST consist of one or more digits, and SHOULD
//. represent the version of the type.
//.
//. If the type identifier does not conform to the format specified above,
//. it is assumed that the entire string represents the _name_ of the type;
//. _namespace_ will be `null` and _version_ will be `0`.
//.
//. If the _version_ is not given, it is assumed to be `0`.
(function(f) {
/* istanbul ignore else */
{
module.exports = f ();
}
} (function() {
// $$type :: String
var $$type = '@@type';
// pattern :: RegExp
var pattern = new RegExp (
'^'
+ '([\\s\\S]+)' // <namespace>
+ '/' // SOLIDUS (U+002F)
+ '([\\s\\S]+?)' // <name>
+ '(?:' // optional non-capturing group {
+ '@' // COMMERCIAL AT (U+0040)
+ '([0-9]+)' // <version>
+ ')?' // }
+ '$'
);
//. ### Usage
//.
//. ```javascript
//. const type = require ('sanctuary-type-identifiers');
//. ```
//.
//. ```javascript
//. > const Identity$prototype = {
//. . '@@type': 'my-package/Identity@1',
//. . '@@show': function() {
//. . return 'Identity (' + show (this.value) + ')';
//. . }
//. . }
//.
//. > const Identity = value =>
//. . Object.assign (Object.create (Identity$prototype), {value})
//.
//. > type (Identity (0))
//. 'my-package/Identity@1'
//.
//. > type.parse (type (Identity (0)))
//. {namespace: 'my-package', name: 'Identity', version: 1}
//. ```
//.
//. ### API
//.
//# type :: Any -> String
//.
//. Takes any value and returns a string which identifies its type. If the
//. value conforms to the [specification][4], the custom type identifier is
//. returned.
//.
//. ```javascript
//. > type (null)
//. 'Null'
//.
//. > type (true)
//. 'Boolean'
//.
//. > type (Identity (0))
//. 'my-package/Identity@1'
//. ```
function type(x) {
return x != null &&
x.constructor != null &&
x.constructor.prototype !== x &&
typeof x[$$type] === 'string' ?
x[$$type] :
(Object.prototype.toString.call (x)).slice ('[object '.length,
-']'.length);
}
//# type.parse :: String -> { namespace :: Nullable String, name :: String, version :: Number }
//.
//. Takes any string and parses it according to the [specification][4],
//. returning an object with `namespace`, `name`, and `version` fields.
//.
//. ```javascript
//. > type.parse ('my-package/List@2')
//. {namespace: 'my-package', name: 'List', version: 2}
//.
//. > type.parse ('nonsense!')
//. {namespace: null, name: 'nonsense!', version: 0}
//.
//. > type.parse (type (Identity (0)))
//. {namespace: 'my-package', name: 'Identity', version: 1}
//. ```
type.parse = function parse(s) {
var namespace = null;
var name = s;
var version = 0;
var groups = pattern.exec (s);
if (groups != null) {
namespace = groups[1];
name = groups[2];
if (groups[3] != null) version = Number (groups[3]);
}
return {namespace: namespace, name: name, version: version};
};
return type;
}));
//. [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
//. [2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
//. [3]: https://docs.npmjs.com/misc/scope
//. [4]: #specification
});
var FL = {
alt: 'fantasy-land/alt',
ap: 'fantasy-land/ap',
bimap: 'fantasy-land/bimap',
chain: 'fantasy-land/chain',
chainRec: 'fantasy-land/chainRec',
map: 'fantasy-land/map',
of: 'fantasy-land/of',
zero: 'fantasy-land/zero'
};
var ordinal = ['first', 'second', 'third', 'fourth', 'fifth'];
var namespace = 'fluture';
var name = 'Future';
var version = 5;
var $$type$1 = namespace + '/' + name + '@' + version;
function List(head, tail){
this.head = head;
this.tail = tail;
}
List.prototype.toJSON = function(){
return toArray(this);
};
var nil = new List(null, null);
nil.tail = nil;
function isNil(list){
return list.tail === list;
}
// cons :: (a, List a) -> List a
// -- O(1) append operation
function cons(head, tail){
return new List(head, tail);
}
// reverse :: List a -> List a
// -- O(n) list reversal
function reverse(xs){
var ys = nil, tail = xs;
while(!isNil(tail)){
ys = cons(tail.head, ys);
tail = tail.tail;
}
return ys;
}
// cat :: (List a, List a) -> List a
// -- O(n) list concatenation
function cat(xs, ys){
var zs = ys, tail = reverse(xs);
while(!isNil(tail)){
zs = cons(tail.head, zs);
tail = tail.tail;
}
return zs;
}
// toArray :: List a -> Array a
// -- O(n) list to Array
function toArray(xs){
var tail = xs, arr = [];
while(!isNil(tail)){
arr.push(tail.head);
tail = tail.tail;
}
return arr;
}
/* c8 ignore next */
var captureStackTrace = Error.captureStackTrace || captureStackTraceFallback;
var _debug = debugHandleNone;
function debugMode(debug){
_debug = debug ? debugHandleAll : debugHandleNone;
}
function debugHandleNone(x){
return x;
}
function debugHandleAll(x, fn, a, b, c){
return fn(a, b, c);
}
function debug(x, fn, a, b, c){
return _debug(x, fn, a, b, c);
}
function captureContext(previous, tag, fn){
return debug(previous, debugCaptureContext, previous, tag, fn);
}
function debugCaptureContext(previous, tag, fn){
var context = {tag: tag, name: ' from ' + tag + ':'};
captureStackTrace(context, fn);
return cons(context, previous);
}
function captureApplicationContext(context, n, f){
return debug(context, debugCaptureApplicationContext, context, n, f);
}
function debugCaptureApplicationContext(context, n, f){
return debugCaptureContext(context, ordinal[n - 1] + ' application of ' + f.name, f);
}
function captureStackTraceFallback(x){
var e = new Error;
if(typeof e.stack === 'string'){
x.stack = x.name + '\n' + e.stack.split('\n').slice(1).join('\n');
/* c8 ignore next 3 */
}else {
x.stack = x.name;
}
}
var sanctuaryShow = createCommonjsModule(function (module) {
//. # sanctuary-show
//.
//. Haskell has a `show` function which can be applied to a compatible value to
//. produce a descriptive string representation of that value. The idea is that
//. the string representation should, if possible, be an expression which would
//. produce the original value if evaluated.
//.
//. This library provides a similar [`show`](#show) function.
//.
//. In general, this property should hold: `eval (show (x)) = x`. In some cases
//. parens are necessary to ensure correct interpretation (`{}`, for example,
//. is an empty block rather than an empty object in some contexts). Thus the
//. property is more accurately stated `eval ('(' + show (x) + ')') = x`.
//.
//. One can make values of a custom type compatible with [`show`](#show) by
//. defining a `@@show` method. For example:
//.
//. ```javascript
//. //# Maybe#@@show :: Maybe a ~> () -> String
//. //.
//. //. ```javascript
//. //. > show (Nothing)
//. //. 'Nothing'
//. //.
//. //. > show (Just (['foo', 'bar', 'baz']))
//. //. 'Just (["foo", "bar", "baz"])'
//. //. ```
//. Maybe.prototype['@@show'] = function() {
//. return this.isNothing ? 'Nothing' : 'Just (' + show (this.value) + ')';
//. };
//. ```
(function(f) {
/* istanbul ignore else */
{
module.exports = f ();
}
} (function() {
// $$show :: String
var $$show = '@@show';
// seen :: Array Any
var seen = [];
// entry :: Object -> String -> String
function entry(o) {
return function(k) {
return show (k) + ': ' + show (o[k]);
};
}
// sortedKeys :: Object -> Array String
function sortedKeys(o) {
return (Object.keys (o)).sort ();
}
//# show :: Showable a => a -> String
//.
//. Returns a useful string representation of the given value.
//.
//. Dispatches to the value's `@@show` method if present.
//.
//. Where practical, `show (eval ('(' + show (x) + ')')) = show (x)`.
//.
//. ```javascript
//. > show (null)
//. 'null'
//.
//. > show (undefined)
//. 'undefined'
//.
//. > show (true)
//. 'true'
//.
//. > show (new Boolean (false))
//. 'new Boolean (false)'
//.
//. > show (-0)
//. '-0'
//.
//. > show (NaN)
//. 'NaN'
//.
//. > show (new Number (Infinity))
//. 'new Number (Infinity)'
//.
//. > show ('foo\n"bar"\nbaz\n')
//. '"foo\\n\\"bar\\"\\nbaz\\n"'
//.
//. > show (new String (''))
//. 'new String ("")'
//.
//. > show (['foo', 'bar', 'baz'])
//. '["foo", "bar", "baz"]'
//.
//. > show ([[[[[0]]]]])
//. '[[[[[0]]]]]'
//.
//. > show ({x: [1, 2], y: [3, 4], z: [5, 6]})
//. '{"x": [1, 2], "y": [3, 4], "z": [5, 6]}'
//. ```
function show(x) {
if (seen.indexOf (x) >= 0) return '<Circular>';
switch (Object.prototype.toString.call (x)) {
case '[object Boolean]':
return typeof x === 'object' ?
'new Boolean (' + show (x.valueOf ()) + ')' :
x.toString ();
case '[object Number]':
return typeof x === 'object' ?
'new Number (' + show (x.valueOf ()) + ')' :
1 / x === -Infinity ? '-0' : x.toString (10);
case '[object String]':
return typeof x === 'object' ?
'new String (' + show (x.valueOf ()) + ')' :
JSON.stringify (x);
case '[object Date]':
return 'new Date (' +
show (isNaN (x.valueOf ()) ? NaN : x.toISOString ()) +
')';
case '[object Error]':
return 'new ' + x.name + ' (' + show (x.message) + ')';
case '[object Arguments]':
return 'function () { return arguments; } (' +
(Array.prototype.map.call (x, show)).join (', ') +
')';
case '[object Array]':
seen.push (x);
try {
return '[' + ((x.map (show)).concat (
sortedKeys (x)
.filter (function(k) { return !(/^\d+$/.test (k)); })
.map (entry (x))
)).join (', ') + ']';
} finally {
seen.pop ();
}
case '[object Object]':
seen.push (x);
try {
return (
$$show in x &&
(x.constructor == null || x.constructor.prototype !== x) ?
x[$$show] () :
'{' + ((sortedKeys (x)).map (entry (x))).join (', ') + '}'
);
} finally {
seen.pop ();
}
case '[object Set]':
seen.push (x);
try {
return 'new Set (' + show (Array.from (x.values ())) + ')';
} finally {
seen.pop ();
}
case '[object Map]':
seen.push (x);
try {
return 'new Map (' + show (Array.from (x.entries ())) + ')';
} finally {
seen.pop ();
}
default:
return String (x);
}
}
return show;
}));
});
/* c8 ignore next */
var setImmediate = typeof setImmediate === 'undefined' ? setImmediateFallback : setImmediate;
function noop(){}
function moop(){ return this }
function call(f, x){ return f(x) }
function setImmediateFallback(f, x){
return setTimeout(f, 0, x);
}
function raise(x){
setImmediate(function rethrowErrorDelayedToEscapePromiseCatch(){
throw x;
});
}
function showArg$1(x){
return sanctuaryShow(x) + ' :: ' + sanctuaryTypeIdentifiers.parse(sanctuaryTypeIdentifiers(x)).name;
}
function error(message){
return new Error(message);
}
function typeError(message){
return new TypeError(message);
}
function invalidArgument(it, at, expected, actual){
return typeError(
it + '() expects its ' + ordinal[at] + ' argument to ' + expected + '.' +
'\n Actual: ' + showArg$1(actual)
);
}
function invalidArgumentOf(expected){
return function(it, at, actual){
return invalidArgument(it, at, expected, actual);
};
}
function invalidArity(f, args){
return new TypeError(
f.name + '() expects to be called with a single argument per invocation\n' +
' Saw: ' + args.length + ' arguments' +
Array.prototype.slice.call(args).map(function(arg, i){
return '\n ' + (
ordinal[i] ?
ordinal[i].charAt(0).toUpperCase() + ordinal[i].slice(1) :
'Argument ' + String(i + 1)
) + ': ' + showArg$1(arg);
}).join('')
);
}
function invalidNamespace(m, x){
return (
'The Future was not created by ' + namespace + '. '
+ 'Make sure you transform other Futures to ' + namespace + ' Futures. '
+ 'Got ' + (x ? ('a Future from ' + x) : 'an unscoped Future') + '.'
+ '\n See: https://github.com/fluture-js/Fluture#casting-futures'
);
}
function invalidVersion(m, x){
return (
'The Future was created by ' + (x < version ? 'an older' : 'a newer')
+ ' version of ' + namespace + '. '
+ 'This means that one of the sources which creates Futures is outdated. '
+ 'Update this source, or transform its created Futures to be compatible.'
+ '\n See: https://github.com/fluture-js/Fluture#casting-futures'
);
}
function invalidFuture(desc, m, s){
var id = sanctuaryTypeIdentifiers.parse(sanctuaryTypeIdentifiers(m));
var info = id.name === name ? '\n' + (
id.namespace !== namespace ? invalidNamespace(m, id.namespace)
: id.version !== version ? invalidVersion(m, id.version)
: 'Nothing seems wrong. Contact the Fluture maintainers.') : '';
return typeError(
desc + ' to be a valid Future.' + info + '\n' +
' Actual: ' + sanctuaryShow(m) + ' :: ' + id.name + (s || '')
);
}
function invalidFutureArgument(it, at, m, s){
return invalidFuture(it + '() expects its ' + ordinal[at] + ' argument', m, s);
}
function ensureError(value, fn){
var message;
try{
if(value instanceof Error) return value;
message = 'A Non-Error was thrown from a Future: ' + sanctuaryShow(value);
}catch (_){
message = 'Something was thrown from a Future, but it could not be converted to String';
}
var e = error(message);
captureStackTrace(e, fn);
return e;
}
function assignUnenumerable(o, prop, value){
Object.defineProperty(o, prop, {value: value, writable: true, configurable: true});
}
function wrapException(caught, callingFuture){
var origin = ensureError(caught, wrapException);
var context = cat(origin.context || nil, callingFuture.context);
var e = error(origin.message);
assignUnenumerable(e, 'future', origin.future || callingFuture);
assignUnenumerable(e, 'reason', origin.reason || origin);
assignUnenumerable(e, 'stack', e.reason.stack);
return withExtraContext(e, context);
}
function withExtraContext(e, context){
assignUnenumerable(e, 'context', context);
assignUnenumerable(e, 'stack', e.stack + contextToStackTrace(context));
return e;
}
function contextToStackTrace(context){
var stack = '', tail = context;
while(tail !== nil){
stack = stack + '\n' + tail.head.stack;
tail = tail.tail;
}
return stack;
}
function isFunction(f){
return typeof f === 'function';
}
function isThenable(m){
return m instanceof Promise || m != null && isFunction(m.then);
}
function isBoolean(f){
return typeof f === 'boolean';
}
function isNumber(f){
return typeof f === 'number';
}
function isUnsigned(n){
return (n === Infinity || isNumber(n) && n > 0 && n % 1 === 0);
}
function isObject(o){
return o !== null && typeof o === 'object';
}
function isIterator(i){
return isObject(i) && isFunction(i.next);
}
function isArray(x){
return Array.isArray(x);
}
function hasMethod(method, x){
return x != null && isFunction(x[method]);
}
function isFunctor(x){
return hasMethod(FL.map, x);
}
function isAlt(x){
return isFunctor(x) && hasMethod(FL.alt, x);
}
function isApply(x){
return isFunctor(x) && hasMethod(FL.ap, x);
}
function isBifunctor(x){
return isFunctor(x) && hasMethod(FL.bimap, x);
}
function isChain(x){
return isApply(x) && hasMethod(FL.chain, x);
}
function Next(x){
return {done: false, value: x};
}
function Done(x){
return {done: true, value: x};
}
function isIteration(x){
return isObject(x) && isBoolean(x.done);
}
/*eslint no-cond-assign:0, no-constant-condition:0 */
function alwaysTrue(){
return true;
}
function getArgs(it){
var args = new Array(it.arity);
for(var i = 1; i <= it.arity; i++){
args[i - 1] = it['$' + String(i)];
}
return args;
}
function showArg(arg){
return ' (' + sanctuaryShow(arg) + ')';
}
var any = {pred: alwaysTrue, error: invalidArgumentOf('be anything')};
var func = {pred: isFunction, error: invalidArgumentOf('be a Function')};
var future = {pred: isFuture, error: invalidFutureArgument};
var positiveInteger = {pred: isUnsigned, error: invalidArgumentOf('be a positive Integer')};
function application(n, f, type, args, prev){
if(args.length < 2 && type.pred(args[0])) return captureApplicationContext(prev, n, f);
var e = args.length > 1 ? invalidArity(f, args) : type.error(f.name, n - 1, args[0]);
captureStackTrace(e, f);
throw withExtraContext(e, prev);
}
function application1(f, type, args){
return application(1, f, type, args, nil);
}
function Future(computation){
var context = application1(Future, func, arguments);
return new Computation(context, computation);
}
function isFuture(x){
return x instanceof Future || sanctuaryTypeIdentifiers(x) === $$type$1;
}
// Compliance with sanctuary-type-identifiers versions 1 and 2.
// To prevent sanctuary-type-identifiers version 3 from identifying 'Future'
// as being of the type denoted by $$type, we ensure that
// Future.constructor.prototype is equal to Future.
Future['@@type'] = $$type$1;
Future.constructor = {prototype: Future};
Future[FL.of] = resolve;
Future[FL.chainRec] = chainRec;
Future.prototype['@@type'] = $$type$1;
Future.prototype['@@show'] = function Future$show(){
return this.toString();
};
Future.prototype.pipe = function Future$pipe(f){
if(!isFunction(f)) throw invalidArgument('Future#pipe', 0, 'be a Function', f);
return f(this);
};
Future.prototype[FL.ap] = function Future$FL$ap(other){
var context = captureContext(nil, 'a Fantasy Land dispatch to ap', Future$FL$ap);
return other._transform(new ApTransformation(context, this));
};
Future.prototype[FL.map] = function Future$FL$map(mapper){
var context = captureContext(nil, 'a Fantasy Land dispatch to map', Future$FL$map);
return this._transform(new MapTransformation(context, mapper));
};
Future.prototype[FL.bimap] = function Future$FL$bimap(lmapper, rmapper){
var context = captureContext(nil, 'a Fantasy Land dispatch to bimap', Future$FL$bimap);
return this._transform(new BimapTransformation(context, lmapper, rmapper));
};
Future.prototype[FL.chain] = function Future$FL$chain(mapper){
var context = captureContext(nil, 'a Fantasy Land dispatch to chain', Future$FL$chain);
return this._transform(new ChainTransformation(context, mapper));
};
Future.prototype[FL.alt] = function Future$FL$alt(other){
var context = captureContext(nil, 'a Fantasy Land dispatch to alt', Future$FL$alt);
return this._transform(new AltTransformation(context, other));
};
Future.prototype.extractLeft = function Future$extractLeft(){
return [];
};
Future.prototype.extractRight = function Future$extractRight(){
return [];
};
Future.prototype._transform = function Future$transform(transformation){
return new Transformer(transformation.context, this, cons(transformation, nil));
};
Future.prototype.isTransformer = false;
Future.prototype.context = nil;
Future.prototype.arity = 0;
Future.prototype.name = 'future';
Future.prototype.toString = function Future$toString(){
return this.name + getArgs(this).map(showArg).join('');
};
Future.prototype.toJSON = function Future$toJSON(){
return {$: $$type$1, kind: 'interpreter', type: this.name, args: getArgs(this)};
};
function createInterpreter(arity, name, interpret){
var Interpreter = function(context, $1, $2, $3){
this.context = context;
this.$1 = $1;
this.$2 = $2;
this.$3 = $3;
};
Interpreter.prototype = Object.create(Future.prototype);
Interpreter.prototype.arity = arity;
Interpreter.prototype.name = name;
Interpreter.prototype._interpret = interpret;
return Interpreter;
}
var Computation =
createInterpreter(1, 'Future', function Computation$interpret(rec, rej, res){
var computation = this.$1, open = false, cancel = noop, cont = function(){ open = true; };
try{
cancel = computation(function Computation$rej(x){
cont = function Computation$rej$cont(){
open = false;
rej(x);
};
if(open){
cont();
}
}, function Computation$res(x){
cont = function Computation$res$cont(){
open = false;
res(x);
};
if(open){
cont();
}
});
}catch(e){
rec(wrapException(e, this));
return noop;
}
if(!(isFunction(cancel) && cancel.length === 0)){
rec(wrapException(typeError(
'The computation was expected to return a nullary cancellation function\n' +
' Actual: ' + sanctuaryShow(cancel)
), this));
return noop;
}
cont();
return function Computation$cancel(){
if(open){
open = false;
cancel && cancel();
}
};
});
var Never = createInterpreter(0, 'never', function Never$interpret(){
return noop;
});
Never.prototype._isNever = true;
var never = new Never(nil);
function isNever(x){
return isFuture(x) && x._isNever === true;
}
var Crash = createInterpreter(1, 'crash', function Crash$interpret(rec){
rec(this.$1);
return noop;
});
function crash(x){
return new Crash(application1(crash, any, arguments), x);
}
var Reject = createInterpreter(1, 'reject', function Reject$interpret(rec, rej){
rej(this.$1);
return noop;
});
Reject.prototype.extractLeft = function Reject$extractLeft(){
return [this.$1];
};
function reject(x){
return new Reject(application1(reject, any, arguments), x);
}
var Resolve = createInterpreter(1, 'resolve', function Resolve$interpret(rec, rej, res){
res(this.$1);
return noop;
});
Resolve.prototype.extractRight = function Resolve$extractRight(){
return [this.$1];
};
function resolve(x){
return new Resolve(application1(resolve, any, arguments), x);
}
//Note: This function is not curried because it's only used to satisfy the
// Fantasy Land ChainRec specification.
function chainRec(step, init){
return resolve(Next(init))._transform(new ChainTransformation(nil, function chainRec$recur(o){
return o.done ?
resolve(o.value) :
step(Next, Done, o.value)._transform(new ChainTransformation(nil, chainRec$recur));
}));
}
var Transformer =
createInterpreter(2, 'transform', function Transformer$interpret(rec, rej, res){
//These are the cold, and hot, transformation stacks. The cold actions are those that
//have yet to run parallel computations, and hot are those that have.
var cold = nil, hot = nil;
//These combined variables define our current state.
// future = the future we are currently forking
// transformation = the transformation to be informed when the future settles
// cancel = the cancel function of the current future
// settled = a boolean indicating whether a new tick should start
// async = a boolean indicating whether we are awaiting a result asynchronously
var future, transformation, cancel = noop, settled, async = true, it;
//Takes a transformation from the top of the hot stack and returns it.
function nextHot(){
var x = hot.head;
hot = hot.tail;
return x;
}
//Takes a transformation from the top of the cold stack and returns it.
function nextCold(){
var x = cold.head;
cold = cold.tail;
return x;
}
//This function is called with a future to use in the next tick.
//Here we "flatten" the actions of another Sequence into our own actions,
//this is the magic that allows for infinitely stack safe recursion because
//actions like ChainAction will return a new Sequence.
//If we settled asynchronously, we call drain() directly to run the next tick.
function settle(m){
settled = true;
future = m;
if(future.isTransformer){
var tail = future.$2;
while(!isNil(tail)){
cold = cons(tail.head, cold);
tail = tail.tail;
}
future = future.$1;
}
if(async) drain();
}
//This function serves as a rejection handler for our current future.
//It will tell the current transformation that the future rejected, and it will
//settle the current tick with the transformation's answer to that.
function rejected(x){
settle(transformation.rejected(x));
}
//This function serves as a resolution handler for our current future.
//It will tell the current transformation that the future resolved, and it will
//settle the current tick with the transformation's answer to that.
function resolved(x){
settle(transformation.resolved(x));
}
//This function is passed into actions when they are "warmed up".
//If the transformation decides that it has its result, without the need to await
//anything else, then it can call this function to force "early termination".
//When early termination occurs, all actions which were stacked prior to the
//terminator will be skipped. If they were already hot, they will also be
//sent a cancel signal so they can cancel their own concurrent computations,
//as their results are no longer needed.
function early(m, terminator){
cancel();
cold = nil;
if(async && transformation !== terminator){
transformation.cancel();
while((it = nextHot()) && it !== terminator) it.cancel();
}
settle(m);
}
//This will cancel the current Future, the current transformation, and all stacked hot actions.
function Sequence$cancel(){
cancel();
transformation && transformation.cancel();
while(it = nextHot()) it.cancel();
}
//This function is called when an exception is caught.
function exception(e){
Sequence$cancel();
settled = true;
cold = hot = nil;
var error = wrapException(e, future);
future = never;
rec(error);
}
//This function serves to kickstart concurrent computations.
//Takes all actions from the cold stack in reverse order, and calls run() on
//each of them, passing them the "early" function. If any of them settles (by
//calling early()), we abort. After warming up all actions in the cold queue,
//we warm up the current transformation as well.
function warmupActions(){
cold = reverse(cold);
while(cold !== nil){
it = cold.head.run(early);
if(settled) return;
hot = cons(it, hot);
cold = cold.tail;
}
transformation = transformation.run(early);
}
//This function represents our main execution loop. By "tick", we've been
//referring to the execution of one iteration in the while-loop below.
function drain(){
async = false;
while(true){
settled = false;
if(transformation = nextCold()){
cancel = future._interpret(exception, rejected, resolved);
if(!settled) warmupActions();
}else if(transformation = nextHot()){
cancel = future._interpret(exception, rejected, resolved);
}else break;
if(settled) continue;
async = true;
return;
}
cancel = future._interpret(exception, rej, res);
}
//Start the execution loop.
settle(this);
//Return the cancellation function.
return Sequence$cancel;
});
Transformer.prototype.isTransformer = true;
Transformer.prototype._transform = function Transformer$_transform(transformation){
return new Transformer(transformation.context, this.$1, cons(transformation, this.$2));
};
Transformer.prototype.toString = function Transformer$toString(){
return toArray(reverse(this.$2)).reduce(function(str, action){
return action.name + getArgs(action).map(showArg).join('') + ' (' + str + ')';
}, this.$1.toString());
};
function BaseTransformation$rejected(x){
this.cancel();
return new Reject(this.context, x);
}
function BaseTransformation$resolved(x){
this.cancel();
return new Resolve(this.context, x);
}
function BaseTransformation$toJSON(){
return {$: $$type$1, kind: 'transformation', type: this.name, args: getArgs(this)};
}
var BaseTransformation = {
rejected: BaseTransformation$rejected,
resolved: BaseTransformation$resolved,
run: moop,
cancel: noop,
context: nil,
arity: 0,
name: 'transform',
toJSON: BaseTransformation$toJSON
};
function wrapHandler(handler){
return function transformationHandler(x){
var m;
try{
m = handler.call(this, x);
}catch(e){
return new Crash(this.context, e);
}
if(isFuture(m)){
return m;
}
return new Crash(this.context, invalidFuture(
this.name + ' expects the return value from the function it\'s given', m,
'\n When called with: ' + sanctuaryShow(x)
));
};
}
function createTransformation(arity, name, prototype){
var Transformation = function(context, $1, $2){
this.context = context;
this.$1 = $1;
this.$2 = $2;
};
Transformation.prototype = Object.create(BaseTransformation);
Transformation.prototype.arity = arity;
Transformation.prototype.name = name;
if(typeof prototype.rejected === 'function'){
Transformation.prototype.rejected = wrapHandler(prototype.rejected);
}
if(typeof prototype.resolved === 'function'){
Transformation.prototype.resolved = wrapHandler(prototype.resolved);
}
if(typeof prototype.run === 'function'){
Transformation.prototype.run = prototype.run;
}
return Transformation;
}
var ApTransformation = createTransformation(1, 'ap', {
resolved: function ApTransformation$resolved(f){
if(isFunction(f)) return this.$1._transform(new MapTransformation(this.context, f));
throw typeError(
'ap expects the second Future to resolve to a Function\n' +
' Actual: ' + sanctuaryShow(f)
);
}
});
var AltTransformation = createTransformation(1, 'alt', {
rejected: function AltTransformation$rejected(){ return this.$1 }
});
var MapTransformation = createTransformation(1, 'map', {
resolved: function MapTransformation$resolved(x){
return new Resolve(this.context, call(this.$1, x));
}
});
var BimapTransformation = createTransformation(2, 'bimap', {
rejected: function BimapTransformation$rejected(x){
return new Reject(this.context, call(this.$1, x));
},
resolved: function BimapTransformation$resolved(x){
return new Resolve(this.context, call(this.$2, x));
}
});
var ChainTransformation = createTransformation(1, 'chain', {
resolved: function ChainTransformation$resolved(x){ return call(this.$1, x) }
});
var After = createInterpreter(2, 'after', function After$interpret(rec, rej, res){
var id = setTimeout(res, this.$1, this.$2);
return function After$cancel(){ clearTimeout(id); };
});
After.prototype.extractRight = function After$extractRight(){
return [this.$2];
};
function alwaysNever$1(_){
return never;
}
function after(time){
var context1 = application1(after, positiveInteger, arguments);
return time === Infinity ? alwaysNever$1 : (function after(value){
var context2 = application(2, after, any, arguments, context1);
return new After(context2, time, value);
});
}
var alternative = {pred: isAlt, error: invalidArgumentOf('have Alt implemented')};
function alt(left){
if(isFuture(left)){
var context1 = application1(alt, future, arguments);
return function alt(right){
var context2 = application(2, alt, future, arguments, context1);
return right._transform(new AltTransformation(context2, left));
};
}
var context = application1(alt, alternative, arguments);
return function alt(right){
application(2, alt, alternative, arguments, context);
return left[FL.alt](right);
};
}
var AndTransformation = createTransformation(1, 'and', {
resolved: function AndTransformation$resolved(){ return this.$1 }
});
function and(left){
var context1 = application1(and, future, arguments);
return function and(right){
var context2 = application(2, and, future, arguments, context1);
return right._transform(new AndTransformation(context2, left));
};
}
var apply = {pred: isApply, error: invalidArgumentOf('have Apply implemented')};
function ap(mx){
if(isFuture(mx)){
var context1 = application1(ap, future, arguments);
return function ap(mf){
var context2 = application(2, ap, future, arguments, context1);
return mf._transform(new ApTransformation(context2, mx));
};
}
var context = application1(ap, apply, arguments);
return function ap(mf){
application(2, ap, apply, arguments, context);
return mx[FL.ap](mf);
};
}
function invalidPromise(p, f, a){
return typeError(
'encaseP() expects the function it\'s given to return a Promise/Thenable'
+ '\n Actual: ' + sanctuaryShow(p) + '\n From calling: ' + sanctuaryShow(f)
+ '\n With: ' + sanctuaryShow(a)
);
}
var EncaseP = createInterpreter(2, 'encaseP', function EncaseP$interpret(rec, rej, res){
var open = true, fn = this.$1, arg = this.$2, p;
try{
p = fn(arg);
}catch(e){
rec(wrapException(e, this));
return noop;
}
if(!isThenable(p)){
rec(wrapException(invalidPromise(p, fn, arg), this));
return noop;
}
p.then(function EncaseP$res(x){
if(open){
open = false;
res(x);
}
}, function EncaseP$rej(x){
if(open){
open = false;
rej(x);
}
});
return function EncaseP$cancel(){ open = false; };
});
function encaseP(f){
var context1 = application1(encaseP, func, arguments);
return function encaseP(x){
var context2 = application(2, encaseP, any, arguments, context1);
return new EncaseP(context2, f, x);
};
}
function attemptP(_){
return encaseP.apply(this, arguments)(undefined);
}
var Encase = createInterpreter(2, 'encase', function Encase$interpret(rec, rej, res){
var fn = this.$1, r;
try{ r = fn(this.$2); }catch(e){ rej(e); return noop }
res(r);
return noop;
});
function encase(f){
var context1 = application1(encase, func, arguments);
return function encase(x){
var context2 = application(2, encase, any, arguments, context1);
return new Encase(context2, f, x);
};
}
function attempt(_){
return encase.apply(this, arguments)(undefined);
}
var bifunctor = {pred: isBifunctor, error: invalidArgumentOf('have Bifunctor implemented')};
function bimap(f){
var context1 = application1(bimap, func, arguments);
return function bimap(g){
var context2 = application(2, bimap, func, arguments, context1);
return function bimap(m){
var context3 = application(3, bimap, bifunctor, arguments, context2);
return isFuture(m) ?
m._transform(new BimapTransformation(context3, f, g)) :
m[FL.bimap](f, g);
};
};
}
var BichainTransformation = createTransformation(2, 'bichain', {
rejected: function BichainTransformation$rejected(x){ return call(this.$1, x) },
resolved: function BichainTransformation$resolved(x){ return call(this.$2, x) }
});
function bichain(f){
var context1 = application1(bichain, func, arguments);
return function bichain(g){
var context2 = application(2, bichain, func, arguments, context1);
return function bichain(m){
var context3 = application(3, bichain, future, arguments, context2);
return m._transform(new BichainTransformation(context3, f, g));
};
};
}
function Eager(future){
var _this = this;
_this.rec = noop;
_this.rej = noop;
_this.res = noop;
_this.crashed = false;
_this.rejected = false;
_this.resolved = false;
_this.value = null;
_this.cancel = future._interpret(function Eager$crash(x){
_this.value = x;
_this.crashed = true;
_this.cancel = noop;
_this.rec(x);
}, function Eager$reject(x){
_this.value = x;
_this.rejected = true;
_this.cancel = noop;
_this.rej(x);
}, function Eager$resolve(x){
_this.value = x;
_this.resolved = true;
_this.cancel = noop;
_this.res(x);
});
}
Eager.prototype = Object.create(Future.prototype);
Eager.prototype._interpret = function Eager$interpret(rec, rej, res){
if(this.crashed) rec(this.value);
else if(this.rejected) rej(this.value);
else if(this.resolved) res(this.value);
else {
this.rec = rec;
this.rej = rej;
this.res = res;
}
return this.cancel;
};
function earlyCrash(early, x){
early(crash(x));
}
function earlyReject(early, x){
early(reject(x));
}
function earlyResolve(early, x){
early(resolve(x));
}
function createParallelTransformation(name, rec, rej, res, prototype){
var ParallelTransformation = createTransformation(1, name, Object.assign({
run: function Parallel$run(early){
var eager = new Eager(this.$1);
var transformation = new ParallelTransformation(this.context, eager);
function Parallel$early(m){ early(m, transformation); }
transformation.cancel = eager._interpret(
function Parallel$rec(x){ rec(Parallel$early, x); },
function Parallel$rej(x){ rej(Parallel$early, x); },
function Parallel$res(x){ res(Parallel$early, x); }
);
return transformation;
}
}, prototype));
return ParallelTransformation;
}
var PairTransformation = createTransformation(1, 'pair', {
resolved: function PairTransformation$resolved(x){
return new Resolve(this.context, [x, this.$1]);
}
});
var BothTransformation =
createParallelTransformation('both', earlyCrash, earlyReject, noop, {
resolved: function BothTransformation$resolved(x){
return this.$1._transform(new PairTransformation(this.context, x));
}
});
function both(left){
var context1 = application1(both, future, arguments);
return function both(right){
var context2 = application(2, both, future, arguments, context1);
return right._transform(new BothTransformation(context2, left));
};
}
var Cold = 0;
var Pending = 1;
var Crashed = 2;
var Rejected = 3;
var Resolved = 4;
function Queued(rec, rej, res){
this[Crashed] = rec;
this[Rejected] = rej;
this[Resolved] = res;
}
var Cache = createInterpreter(1, 'cache', function Cache$interpret(rec, rej, res){
var cancel = noop;
switch(this._state){
/* c8 ignore next 4 */
case Pending: cancel = this._addToQueue(rec, rej, res); break;
case Crashed: rec(this._value); break;
case Rejected: rej(this._value); break;
case Resolved: res(this._value); break;
default:
this._queue = [];
cancel = this._addToQueue(rec, rej, res);
this.run();
}
return cancel;
});
Cache.prototype._cancel = noop;
Cache.prototype._queue = null;
Cache.prototype._queued = 0;
Cache.prototype._value = undefined;
Cache.prototype._state = Cold;
Cache.prototype.extractLeft = function Cache$extractLeft(){
return this._state === Rejected ? [this._value] : [];
};
Cache.prototype.extractRight = function Cache$extractRight(){
return this._state === Resolved ? [this._value] : [];
};
Cache.prototype._addToQueue = function Cache$addToQueue(rec, rej, res){
var _this = this;
if(_this._state > Pending) return noop;
var i = _this._queue.push(new Queued(rec, rej, res)) - 1;
_this._queued = _this._queued + 1;
return function Cache$removeFromQueue(){
if(_this._state > Pending) return;
_this._queue[i] = undefined;
_this._queued = _this._queued - 1;
if(_this._queued === 0) _this.reset();
};
};
Cache.prototype._drainQueue = function Cache$drainQueue(){
if(this._state <= Pending) return;
if(this._queued === 0) return;
var queue = this._queue;
var length = queue.length;
var state = this._state;
var value = this._value;
for(var i = 0; i < length; i++){
queue[i] && queue[i][state](value);
queue[i] = undefined;
}
this._queue = undefined;
this._queued = 0;
};
Cache.prototype.crash = function Cache$crash(error){
if(this._state > Pending) return;
this._value = error;
this._state = Crashed;
this._drainQueue();
};
Cache.prototype.reject = function Cache$reject(reason){
if(this._state > Pending) return;
this._value = reason;
this._state = Rejected;
this._drainQueue();
};
Cache.prototype.resolve = function Cache$resolve(value){
if(this._state > Pending) return;
this._value = value;
this._state = Resolved;
this._drainQueue();
};
Cache.prototype.run = function Cache$run(){
var _this = this;
if(_this._state > Cold) return;
_this._state = Pending;
_this._cancel = _this.$1._interpret(
function Cache$fork$rec(x){ _this.crash(x); },
function Cache$fork$rej(x){ _this.reject(x); },
function Cache$fork$res(x){ _this.resolve(x); }
);
};
Cache.prototype.reset = function Cache$reset(){
if(this._state === Cold) return;
if(this._state === Pending) this._cancel();
this._cancel = noop;
this._queue = [];
this._queued = 0;
this._value = undefined;
this._state = Cold;
};
function cache(m){
return new Cache(application1(cache, future, arguments), m);
}
var ChainRejTransformation = createTransformation(1, 'chainRej', {
rejected: function ChainRejTransformation$rejected(x){ return call(this.$1, x) }
});
function chainRej(f){
var context1 = application1(chainRej, func, arguments);
return function chainRej(m){
var context2 = application(2, chainRej, future, arguments, context1);
return m._transform(new ChainRejTransformation(context2, f));
};
}
var monad = {pred: isChain, error: invalidArgumentOf('have Chain implemented')};
function chain(f){
var context1 = application1(chain, func, arguments);
return function chain(m){
var context2 = application(2, chain, monad, arguments, context1);
return isFuture(m) ?
m._transform(new ChainTransformation(context2, f)) :
m[FL.chain](f);
};
}
function done(callback){
var context1 = application1(done, func, arguments);
function done$res(x){
callback(null, x);
}
return function done(m){
application(2, done, future, arguments, context1);
return m._interpret(raise, callback, done$res);
};
}
function extractLeft(m){
application1(extractLeft, future, arguments);
return m.extractLeft();
}
function extractRight(m){
application1(extractRight, future, arguments);
return m.extractRight();
}
var CoalesceTransformation = createTransformation(2, 'coalesce', {
rejected: function CoalesceTransformation$rejected(x){
return new Resolve(this.context, call(this.$1, x));
},
resolved: function CoalesceTransformation$resolved(x){
return new Resolve(this.context, call(this.$2, x));
}
});
function coalesce(f){
var context1 = application1(coalesce, func, arguments);
return function coalesce(g){
var context2 = application(2, coalesce, func, arguments, context1);
return function coalesce(m){
var context3 = application(3, coalesce, future, arguments, context2);
return m._transform(new CoalesceTransformation(context3, f, g));
};
};
}
function forkCatch(f){
var context1 = application1(forkCatch, func, arguments);
return function forkCatch(g){
var context2 = application(2, forkCatch, func, arguments, context1);
return function forkCatch(h){
var context3 = application(3, forkCatch, func, arguments, context2);
return function forkCatch(m){
application(4, forkCatch, future, arguments, context3);
return m._interpret(f, g, h);
};
};
};
}
function fork(f){
var context1 = application1(fork, func, arguments);
return function fork(g){
var context2 = application(2, fork, func, arguments, context1);
return function fork(m){
application(3, fork, future, arguments, context2);
return m._interpret(raise, f, g);
};
};
}
var Undetermined = 0;
var Synchronous = 1;
var Asynchronous = 2;
/*eslint consistent-return: 0 */
function invalidIteration(o){
return typeError(
'The iterator did not return a valid iteration from iterator.next()\n' +
' Actual: ' + sanctuaryShow(o)
);
}
function invalidState(x){
return invalidFuture(
'go() expects the value produced by the iterator', x,
'\n Tip: If you\'re using a generator, make sure you always yield a Future'
);
}
var Go = createInterpreter(1, 'go', function Go$interpret(rec, rej, res){
var _this = this, timing = Undetermined, cancel = noop, state, value, iterator;
function crash(e){
rec(wrapException(e, _this));
}
try{
iterator = _this.$1();
}catch(e){
crash(e);
return noop;
}
if(!isIterator(iterator)){
crash(invalidArgument('go', 0, 'return an iterator, maybe you forgot the "*"', iterator));
return noop;
}
function resolved(x){
value = x;
if(timing === Asynchronous) return drain();
timing = Synchronous;
}
function drain(){
//eslint-disable-next-line no-constant-condition
while(true){
try{
state = iterator.next(value);
}catch(e){
return crash(e);
}
if(!isIteration(state)) return crash(invalidIteration(state));
if(state.done) break;
if(!isFuture(state.value)){
return crash(invalidState(state.value));
}
timing = Undetermined;
cancel = state.value._interpret(crash, rej, resolved);
if(timing === Undetermined) return timing = Asynchronous;
}
res(state.value);
}
drain();
return function Go$cancel(){ cancel(); };
});
function go(generator){
return new Go(application1(go, func, arguments), generator);
}
function invalidDisposal(m, f, x){
return invalidFuture(
'hook() expects the return value from the first function it\'s given', m,
'\n From calling: ' + sanctuaryShow(f) + '\n With: ' + sanctuaryShow(x)
);
}
function invalidConsumption(m, f, x){
return invalidFuture(
'hook() expects the return value from the second function it\'s given', m,
'\n From calling: ' + sanctuaryShow(f) + '\n With: ' + sanctuaryShow(x)
);
}
var Hook = createInterpreter(3, 'hook', function Hook$interpret(rec, rej, res){
var _this = this, _acquire = this.$1, _dispose = this.$2, _consume = this.$3;
var cancel, cancelConsume = noop, resource, value, cont = noop;
function Hook$done(){
cont(value);
}
function Hook$rec(x){
rec(wrapException(x, _this));
}
function Hook$dispose(){
var disposal;
try{
disposal = _dispose(resource);
}catch(e){
return Hook$rec(e);
}
if(!isFuture(disposal)){
return Hook$rec(invalidDisposal(disposal, _dispose, resource));
}
cancel = Hook$cancelDisposal;
disposal._interpret(Hook$rec, Hook$disposalRejected, Hook$done);
}
function Hook$cancelConsumption(){
cancelConsume();
Hook$dispose();
Hook$cancelDisposal();
}
function Hook$cancelDisposal(){
cont = noop;
}
function Hook$disposalRejected(x){
Hook$rec(new Error('The disposal Future rejected with ' + sanctuaryShow(x)));
}
function Hook$consumptionException(x){
cont = Hook$rec;
value = x;
Hook$dispose();
}
function Hook$consumptionRejected(x){
cont = rej;
value = x;
Hook$dispose();
}
function Hook$consumptionResolved(x){
cont = res;
value = x;
Hook$dispose();
}
function Hook$consume(x){
resource = x;
var consumption;
try{
consumption = _consume(resource);
}catch(e){
return Hook$consumptionException(e);
}
if(!isFuture(consumption)){
return Hook$consumptionException(invalidConsumption(consumption, _consume, resource));
}
cancel = Hook$cancelConsumption;
cancelConsume = consumption._interpret(
Hook$consumptionException,
Hook$consumptionRejected,
Hook$consumptionResolved
);
}
var cancelAcquire = _acquire._interpret(Hook$rec, rej, Hook$consume);
cancel = cancel || cancelAcquire;
return function Hook$fork$cancel(){
rec = raise;
cancel();
};
});
function hook(acquire){
var context1 = application1(hook, future, arguments);
return function hook(dispose){
var context2 = application(2, hook, func, arguments, context1);
return function hook(consume){
var context3 = application(3, hook, func, arguments, context2);
return new Hook(context3, acquire, dispose, consume);
};
};
}
var LastlyTransformation = createTransformation(1, 'lastly', {
rejected: function LastlyAction$rejected(x){
return this.$1._transform(new AndTransformation(this.context, new Reject(this.context, x)));
},
resolved: function LastlyAction$resolved(x){
return this.$1._transform(new AndTransformation(this.context, new Resolve(this.context, x)));
}
});
function lastly(cleanup){
var context1 = application1(lastly, future, arguments);
return function lastly(program){
var context2 = application(2, lastly, future, arguments, context1);
return program._transform(new LastlyTransformation(context2, cleanup));
};
}
var MapRejTransformation = createTransformation(1, 'mapRej', {
rejected: function MapRejTransformation$rejected(x){
return new Reject(this.context, call(this.$1, x));
}
});
function mapRej(f){
var context1 = application1(mapRej, func, arguments);
return function mapRej(m){
var context2 = application(2, mapRej, future, arguments, context1);
return m._transform(new MapRejTransformation(context2, f));
};
}
var functor = {pred: isFunctor, error: invalidArgumentOf('have Functor implemented')};
function map(f){
var context1 = application1(map, func, arguments);
return function map(m){
var context2 = application(2, map, functor, arguments, context1);
return isFuture(m) ?
m._transform(new MapTransformation(context2, f)) :
m[FL.map](f);
};
}
var Node = createInterpreter(1, 'node', function Node$interpret(rec, rej, res){
function Node$done(err, val){
cont = err ? function EncaseN3$rej(){
open = false;
rej(err);
} : function EncaseN3$res(){
open = false;
res(val);
};
if(open){
cont();
}
}
var open = false, cont = function(){ open = true; };
try{
call(this.$1, Node$done);
}catch(e){
rec(wrapException(e, this));
open = false;
return noop;
}
cont();
return function Node$cancel(){ open = false; };
});
function node(f){
return new Node(application1(node, func, arguments), f);
}
var ParallelApTransformation =
createParallelTransformation('pap', earlyCrash, earlyReject, noop, {
resolved: function ParallelApTransformation$resolved(f){
if(isFunction(f)) return this.$1._transform(new MapTransformation(this.context, f));
throw typeError(
'pap expects the second Future to resolve to a Function\n' +
' Actual: ' + sanctuaryShow(f)
);
}
});
function pap(mx){
var context1 = application1(pap, future, arguments);
return function pap(mf){
var context2 = application(2, pap, future, arguments, context1);
return mf._transform(new ParallelApTransformation(context2, mx));
};
}
function isFutureArray(xs){
if(!isArray(xs)) return false;
for(var i = 0; i < xs.length; i++){
if(!isFuture(xs[i])) return false;
}
return true;
}
var futureArray = {
pred: isFutureArray,
error: invalidArgumentOf('be an Array of valid Futures')
};
var Parallel = createInterpreter(2, 'parallel', function Parallel$interpret(rec, rej, res){
var _this = this, futures = this.$2, length = futures.length;
var max = Math.min(this.$1, length), cancels = new Array(length), out = new Array(length);
var cursor = 0, running = 0, blocked = false, cont = noop;
function Parallel$cancel(){
rec = noop;
rej = noop;
res = noop;
cursor = length;
for(var n = 0; n < length; n++) cancels[n] && cancels[n]();
}
function Parallel$run(idx){
running++;
cancels[idx] = futures[idx]._interpret(function Parallel$rec(e){
cont = rec;
cancels[idx] = noop;
Parallel$cancel();
cont(wrapException(e, _this));
}, function Parallel$rej(reason){
cont = rej;
cancels[idx] = noop;
Parallel$cancel();
cont(reason);
}, function Parallel$res(value){
cancels[idx] = noop;
out[idx] = value;
running--;
if(cursor === length && running === 0) res(out);
else if(blocked) Parallel$drain();
});
}
function Parallel$drain(){
blocked = false;
while(cursor < length && running < max) Parallel$run(cursor++);
blocked = true;
}
Parallel$drain();
return Parallel$cancel;
});
var emptyArray = resolve([]);
function parallel$1(max){
var context1 = application1(parallel$1, positiveInteger, arguments);
return function parallel(ms){
var context2 = application(2, parallel, futureArray, arguments, context1);
return ms.length === 0 ? emptyArray : new Parallel(context2, max, ms);
};
}
var RaceTransformation =
createParallelTransformation('race', earlyCrash, earlyReject, earlyResolve, {});
function race(left){
var context1 = application1(race, future, arguments);
return function race(right){
var context2 = application(2, race, future, arguments, context1);
return right._transform(new RaceTransformation(context2, left));
};
}
function ConcurrentFuture (sequential){
this.sequential = sequential;
}
ConcurrentFuture.prototype = Object.create(Par.prototype);
function Par (sequential){
if(!isFuture(sequential)) throw invalidFutureArgument(Par.name, 0, sequential);
return new ConcurrentFuture(sequential);
}
var $$type = namespace + '/ConcurrentFuture@' + version;
var zeroInstance = new ConcurrentFuture(never);
// Compliance with sanctuary-type-identifiers versions 1 and 2.
// To prevent sanctuary-type-identifiers version 3 from identifying
// 'Par' as being of the type denoted by $$type, we ensure that
// Par.constructor.prototype is equal to Par.
Par['@@type'] = $$type;
Par.constructor = {prototype: Par};
Par[FL.of] = function Par$of(x){
return new ConcurrentFuture(resolve(x));
};
Par[FL.zero] = function Par$zero(){
return zeroInstance;
};
Par.prototype['@@type'] = $$type;
Par.prototype['@@show'] = function Par$show(){
return this.toString();
};
Par.prototype.toString = function Par$toString(){
return 'Par (' + this.sequential.toString() + ')';
};
Par.prototype[FL.map] = function Par$FL$map(f){
var context = captureContext(
nil,
'a Fantasy Land dispatch to map via ConcurrentFuture',
Par$FL$map
);
return new ConcurrentFuture(this.sequential._transform(new MapTransformation(context, f)));
};
Par.prototype[FL.ap] = function Par$FL$ap(other){
var context = captureContext(
nil,
'a Fantasy Land dispatch to ap via ConcurrentFuture',
Par$FL$ap
);
return new ConcurrentFuture(other.sequential._transform(
new ParallelApTransformation(context, this.sequential)
));
};
Par.prototype[FL.alt] = function Par$FL$alt(other){
var context = captureContext(
nil,
'a Fantasy Land dispatch to alt via ConcurrentFuture',
Par$FL$alt
);
return new ConcurrentFuture(other.sequential._transform(
new RaceTransformation(context, this.sequential)
));
};
function isParallel(x){
return x instanceof ConcurrentFuture || sanctuaryTypeIdentifiers(x) === $$type;
}
function promise(m){
application1(promise, future, arguments);
return new Promise(function promise$computation(res, rej){
m._interpret(rej, rej, res);
});
}
var RejectAfter =
createInterpreter(2, 'rejectAfter', function RejectAfter$interpret(rec, rej){
var id = setTimeout(rej, this.$1, this.$2);
return function RejectAfter$cancel(){ clearTimeout(id); };
});
RejectAfter.prototype.extractLeft = function RejectAfter$extractLeft(){
return [this.$2];
};
function alwaysNever(_){
return never;
}
function rejectAfter(time){
var context1 = application1(rejectAfter, positiveInteger, arguments);
return time === Infinity ? alwaysNever : (function rejectAfter(value){
var context2 = application(2, rejectAfter, any, arguments, context1);
return new RejectAfter(context2, time, value);
});
}
var parallel = {pred: isParallel, error: invalidArgumentOf('be a ConcurrentFuture')};
function seq(par){
application1(seq, parallel, arguments);
return par.sequential;
}
var SwapTransformation = createTransformation(0, 'swap', {
resolved: function SwapTransformation$resolved(x){
return new Reject(this.context, x);
},
rejected: function SwapTransformation$rejected(x){
return new Resolve(this.context, x);
}
});
function swap(m){
var context = application1(swap, future, arguments);
return m._transform(new SwapTransformation(context));
}
function value(res){
var context1 = application1(value, func, arguments);
return function value(m){
application(2, value, future, arguments, context1);
function value$rej(x){
raise(error(
'Future#value was called on a rejected Future\n' +
' Rejection: ' + sanctuaryShow(x) + '\n' +
' Future: ' + sanctuaryShow(m)
));
}
return m._interpret(raise, value$rej, res);
};
}
var Fluture = /*#__PURE__*/Object.freeze({
__proto__: null,
'default': Future,
Future: Future,
isFuture: isFuture,
isNever: isNever,
never: never,
reject: reject,
resolve: resolve,
after: after,
alt: alt,
and: and,
ap: ap,
attemptP: attemptP,
attempt: attempt,
bimap: bimap,
bichain: bichain,
both: both,
cache: cache,
chainRej: chainRej,
chain: chain,
done: done,
encaseP: encaseP,
encase: encase,
extractLeft: extractLeft,
extractRight: extractRight,
coalesce: coalesce,
forkCatch: forkCatch,
fork: fork,
go: go,
hook: hook,
lastly: lastly,
mapRej: mapRej,
map: map,
node: node,
pap: pap,
parallel: parallel$1,
Par: Par,
promise: promise,
race: race,
rejectAfter: rejectAfter,
seq: seq,
swap: swap,
value: value,
debugMode: debugMode
});
var index_cjs = Object.assign(Future, Fluture);
return index_cjs;
}());
/** Fluture license
The MIT License (MIT)
Copyright (c) 2020 Aldwin Vlasblom
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/** sanctuary-show license
The MIT License (MIT)
Copyright (c) 2020 Sanctuary
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/** sanctuary-type-identifiers license
The MIT License (MIT)
Copyright (c) 2019 Sanctuary
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
================================================
FILE: dist/module.js
================================================
/**
* Fluture bundled; version 14.0.0
*/
/// <reference types="https://cdn.jsdelivr.net/gh/fluture-js/Fluture@14.0.0/index.d.ts" />
function createCommonjsModule(fn) {
var module = { exports: {} };
return fn(module, module.exports), module.exports;
}
/*
@@@@@@@ @@@@@@@ @@
@@ @@ @@ @@ @@@
@@ @@@ @@ @@ @@ @@@ @@ @@ @@@@@@ @@ @@@ @@ @@@ @@@@
@@ @@ @@@ @@ @@ @@ @@@ @@ @@@ @@ @@@ @@@ @@ @@@ @@
@@ @@ @@@ @@ @@ @@ @@@ @@ @@@ @@ @@@ @@@ @@ @@@@@@@@
@@ @@ @@@ @@ @@ @@ @@@ @@ @@@ @@ @@@ @@@ @@ @@@
@@ @@@ @@@@@ @@ @@@ @@@@@ @@@ @@@ @@ @@@@@@ @@@@@
@@ @@ @@ @@
@@@@@@@ @@@@@@@ @@@@@ @@
*/
var sanctuaryTypeIdentifiers = createCommonjsModule(function (module) {
//. # sanctuary-type-identifiers
//.
//. A type is a set of values. Boolean, for example, is the type comprising
//. `true` and `false`. A value may be a member of multiple types (`42` is a
//. member of Number, PositiveNumber, Integer, and many other types).
//.
//. In certain situations it is useful to divide JavaScript values into
//. non-overlapping types. The language provides two constructs for this
//. purpose: the [`typeof`][1] operator and [`Object.prototype.toString`][2].
//. Each has pros and cons, but neither supports user-defined types.
//.
//. sanctuary-type-identifiers comprises:
//.
//. - an npm and browser -compatible package for deriving the
//. _type identifier_ of a JavaScript value; and
//. - a specification which authors may follow to specify type
//. identifiers for their types.
//.
//. ### Specification
//.
//. For a type to be compatible with the algorithm:
//.
//. - every member of the type MUST have a `@@type` property
//. (the _type identifier_); and
//.
//. - the type identifier MUST be a string primitive and SHOULD have
//. format `'<namespace>/<name>[@<version>]'`, where:
//.
//. - `<namespace>` MUST consist of one or more characters, and
//. SHOULD equal the name of the npm package which defines the
//. type (including [scope][3] where appropriate);
//.
//. - `<name>` MUST consist of one or more characters, and SHOULD
//. be the unique name of the type; and
//.
//. - `<version>` MUST consist of one or more digits, and SHOULD
//. represent the version of the type.
//.
//. If the type identifier does not conform to the format specified above,
//. it is assumed that the entire string represents the _name_ of the type;
//. _namespace_ will be `null` and _version_ will be `0`.
//.
//. If the _version_ is not given, it is assumed to be `0`.
(function(f) {
/* istanbul ignore else */
{
module.exports = f ();
}
} (function() {
// $$type :: String
var $$type = '@@type';
// pattern :: RegExp
var pattern = new RegExp (
'^'
+ '([\\s\\S]+)' // <namespace>
+ '/' // SOLIDUS (U+002F)
+ '([\\s\\S]+?)' // <name>
+ '(?:' // optional non-capturing group {
+ '@' // COMMERCIAL AT (U+0040)
+ '([0-9]+)' // <version>
+ ')?' // }
+ '$'
);
//. ### Usage
//.
//. ```javascript
//. const type = require ('sanctuary-type-identifiers');
//. ```
//.
//. ```javascript
//. > const Identity$prototype = {
//. . '@@type': 'my-package/Identity@1',
//. . '@@show': function() {
//. . return 'Identity (' + show (this.value) + ')';
//. . }
//. . }
//.
//. > const Identity = value =>
//. . Object.assign (Object.create (Identity$prototype), {value})
//.
//. > type (Identity (0))
//. 'my-package/Identity@1'
//.
//. > type.parse (type (Identity (0)))
//. {namespace: 'my-package', name: 'Identity', version: 1}
//. ```
//.
//. ### API
//.
//# type :: Any -> String
//.
//. Takes any value and returns a string which identifies its type. If the
//. value conforms to the [specification][4], the custom type identifier is
//. returned.
//.
//. ```javascript
//. > type (null)
//. 'Null'
//.
//. > type (true)
//. 'Boolean'
//.
//. > type (Identity (0))
//. 'my-package/Identity@1'
//. ```
function type(x) {
return x != null &&
x.constructor != null &&
x.constructor.prototype !== x &&
typeof x[$$type] === 'string' ?
x[$$type] :
(Object.prototype.toString.call (x)).slice ('[object '.length,
-']'.length);
}
//# type.parse :: String -> { namespace :: Nullable String, name :: String, version :: Number }
//.
//. Takes any string and parses it according to the [specification][4],
//. returning an object with `namespace`, `name`, and `version` fields.
//.
//. ```javascript
//. > type.parse ('my-package/List@2')
//. {namespace: 'my-package', name: 'List', version: 2}
//.
//. > type.parse ('nonsense!')
//. {namespace: null, name: 'nonsense!', version: 0}
//.
//. > type.parse (type (Identity (0)))
//. {namespace: 'my-package', name: 'Identity', version: 1}
//. ```
type.parse = function parse(s) {
var namespace = null;
var name = s;
var version = 0;
var groups = pattern.exec (s);
if (groups != null) {
namespace = groups[1];
name = groups[2];
if (groups[3] != null) version = Number (groups[3]);
}
return {namespace: namespace, name: name, version: version};
};
return type;
}));
//. [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
//. [2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
//. [3]: https://docs.npmjs.com/misc/scope
//. [4]: #specification
});
var FL = {
alt: 'fantasy-land/alt',
ap: 'fantasy-land/ap',
bimap: 'fantasy-land/bimap',
chain: 'fantasy-land/chain',
chainRec: 'fantasy-land/chainRec',
map: 'fantasy-land/map',
of: 'fantasy-land/of',
zero: 'fantasy-land/zero'
};
var ordinal = ['first', 'second', 'third', 'fourth', 'fifth'];
var namespace = 'fluture';
var name = 'Future';
var version = 5;
var $$type$1 = namespace + '/' + name + '@' + version;
function List(head, tail){
this.head = head;
this.tail = tail;
}
List.prototype.toJSON = function(){
return toArray(this);
};
var nil = new List(null, null);
nil.tail = nil;
function isNil(list){
return list.tail === list;
}
// cons :: (a, List a) -> List a
// -- O(1) append operation
function cons(head, tail){
return new List(head, tail);
}
// reverse :: List a -> List a
// -- O(n) list reversal
function reverse(xs){
var ys = nil, tail = xs;
while(!isNil(tail)){
ys = cons(tail.head, ys);
tail = tail.tail;
}
return ys;
}
// cat :: (List a, List a) -> List a
// -- O(n) list concatenation
function cat(xs, ys){
var zs = ys, tail = reverse(xs);
while(!isNil(tail)){
zs = cons(tail.head, zs);
tail = tail.tail;
}
return zs;
}
// toArray :: List a -> Array a
// -- O(n) list to Array
function toArray(xs){
var tail = xs, arr = [];
while(!isNil(tail)){
arr.push(tail.head);
tail = tail.tail;
}
return arr;
}
/* c8 ignore next */
var captureStackTrace = Error.captureStackTrace || captureStackTraceFallback;
var _debug = debugHandleNone;
function debugMode(debug){
_debug = debug ? debugHandleAll : debugHandleNone;
}
function debugHandleNone(x){
return x;
}
function debugHandleAll(x, fn, a, b, c){
return fn(a, b, c);
}
function debug(x, fn, a, b, c){
return _debug(x, fn, a, b, c);
}
function captureContext(previous, tag, fn){
return debug(previous, debugCaptureContext, previous, tag, fn);
}
function debugCaptureContext(previous, tag, fn){
var context = {tag: tag, name: ' from ' + tag + ':'};
captureStackTrace(context, fn);
return cons(context, previous);
}
function captureApplicationContext(context, n, f){
return debug(context, debugCaptureApplicationContext, context, n, f);
}
function debugCaptureApplicationContext(context, n, f){
return debugCaptureContext(context, ordinal[n - 1] + ' application of ' + f.name, f);
}
function captureStackTraceFallback(x){
var e = new Error;
if(typeof e.stack === 'string'){
x.stack = x.name + '\n' + e.stack.split('\n').slice(1).join('\n');
/* c8 ignore next 3 */
}else {
x.stack = x.name;
}
}
var sanctuaryShow = createCommonjsModule(function (module) {
//. # sanctuary-show
//.
//. Haskell has a `show` function which can be applied to a compatible value to
//. produce a descriptive string representation of that value. The idea is that
//. the string representation should, if possible, be an expression which would
//. produce the original value if evaluated.
//.
//. This library provides a similar [`show`](#show) function.
//.
//. In general, this property should hold: `eval (show (x)) = x`. In some cases
//. parens are necessary to ensure correct interpretation (`{}`, for example,
//. is an empty block rather than an empty object in some contexts). Thus the
//. property is more accurately stated `eval ('(' + show (x) + ')') = x`.
//.
//. One can make values of a custom type compatible with [`show`](#show) by
//. defining a `@@show` method. For example:
//.
//. ```javascript
//. //# Maybe#@@show :: Maybe a ~> () -> String
//. //.
//. //. ```javascript
//. //. > show (Nothing)
//. //. 'Nothing'
//. //.
//. //. > show (Just (['foo', 'bar', 'baz']))
//. //. 'Just (["foo", "bar", "baz"])'
//. //. ```
//. Maybe.prototype['@@show'] = function() {
//. return this.isNothing ? 'Nothing' : 'Just (' + show (this.value) + ')';
//. };
//. ```
(function(f) {
/* istanbul ignore else */
{
module.exports = f ();
}
} (function() {
// $$show :: String
var $$show = '@@show';
// seen :: Array Any
var seen = [];
// entry :: Object -> String -> String
function entry(o) {
return function(k) {
return show (k) + ': ' + show (o[k]);
};
}
// sortedKeys :: Object -> Array String
function sortedKeys(o) {
return (Object.keys (o)).sort ();
}
//# show :: Showable a => a -> String
//.
//. Returns a useful string representation of the given value.
//.
//. Dispatches to the value's `@@show` method if present.
//.
//. Where practical, `show (eval ('(' + show (x) + ')')) = show (x)`.
//.
//. ```javascript
//. > show (null)
//. 'null'
//.
//. > show (undefined)
//. 'undefined'
//.
//. > show (true)
//. 'true'
//.
//. > show (new Boolean (false))
//. 'new Boolean (false)'
//.
//. > show (-0)
//. '-0'
//.
//. > show (NaN)
//. 'NaN'
//.
//. > show (new Number (Infinity))
//. 'new Number (Infinity)'
//.
//. > show ('foo\n"bar"\nbaz\n')
//. '"foo\\n\\"bar\\"\\nbaz\\n"'
//.
//. > show (new String (''))
//. 'new String ("")'
//.
//. > show (['foo', 'bar', 'baz'])
//. '["foo", "bar", "baz"]'
//.
//. > show ([[[[[0]]]]])
//. '[[[[[0]]]]]'
//.
//. > show ({x: [1, 2], y: [3, 4], z: [5, 6]})
//. '{"x": [1, 2], "y": [3, 4], "z": [5, 6]}'
//. ```
function show(x) {
if (seen.indexOf (x) >= 0) return '<Circular>';
switch (Object.prototype.toString.call (x)) {
case '[object Boolean]':
return typeof x === 'object' ?
'new Boolean (' + show (x.valueOf ()) + ')' :
x.toString ();
case '[object Number]':
return typeof x === 'object' ?
'new Number (' + show (x.valueOf ()) + ')' :
1 / x === -Infinity ? '-0' : x.toString (10);
case '[object String]':
return typeof x === 'object' ?
'new String (' + show (x.valueOf ()) + ')' :
JSON.stringify (x);
case '[object Date]':
return 'new Date (' +
show (isNaN (x.valueOf ()) ? NaN : x.toISOString ()) +
')';
case '[object Error]':
return 'new ' + x.name + ' (' + show (x.message) + ')';
case '[object Arguments]':
return 'function () { return arguments; } (' +
(Array.prototype.map.call (x, show)).join (', ') +
')';
case '[object Array]':
seen.push (x);
try {
return '[' + ((x.map (show)).concat (
sortedKeys (x)
.filter (function(k) { return !(/^\d+$/.test (k)); })
.map (entry (x))
)).join (', ') + ']';
} finally {
seen.pop ();
}
case '[object Object]':
seen.push (x);
try {
return (
$$show in x &&
(x.constructor == null || x.constructor.prototype !== x) ?
x[$$show] () :
'{' + ((sortedKeys (x)).map (entry (x))).join (', ') + '}'
);
} finally {
seen.pop ();
}
case '[object Set]':
seen.push (x);
try {
return 'new Set (' + show (Array.from (x.values ())) + ')';
} finally {
seen.pop ();
}
case '[object Map]':
seen.push (x);
try {
return 'new Map (' + show (Array.from (x.entries ())) + ')';
} finally {
seen.pop ();
}
default:
return String (x);
}
}
return show;
}));
});
/* c8 ignore next */
var setImmediate = typeof setImmediate === 'undefined' ? setImmediateFallback : setImmediate;
function noop(){}
function moop(){ return this }
function call(f, x){ return f(x) }
function setImmediateFallback(f, x){
return setTimeout(f, 0, x);
}
function raise(x){
setImmediate(function rethrowErrorDelayedToEscapePromiseCatch(){
throw x;
});
}
function showArg$1(x){
return sanctuaryShow(x) + ' :: ' + sanctuaryTypeIdentifiers.parse(sanctuaryTypeIdentifiers(x)).name;
}
function error(message){
return new Error(message);
}
function typeError(message){
return new TypeError(message);
}
function invalidArgument(it, at, expected, actual){
return typeError(
it + '() expects its ' + ordinal[at] + ' argument to ' + expected + '.' +
'\n Actual: ' + showArg$1(actual)
);
}
function invalidArgumentOf(expected){
return function(it, at, actual){
return invalidArgument(it, at, expected, actual);
};
}
function invalidArity(f, args){
return new TypeError(
f.name + '() expects to be called with a single argument per invocation\n' +
' Saw: ' + args.length + ' arguments' +
Array.prototype.slice.call(args).map(function(arg, i){
return '\n ' + (
ordinal[i] ?
ordinal[i].charAt(0).toUpperCase() + ordinal[i].slice(1) :
'Argument ' + String(i + 1)
) + ': ' + showArg$1(arg);
}).join('')
);
}
function invalidNamespace(m, x){
return (
'The Future was not created by ' + namespace + '. '
+ 'Make sure you transform other Futures to ' + namespace + ' Futures. '
+ 'Got ' + (x ? ('a Future from ' + x) : 'an unscoped Future') + '.'
+ '\n See: https://github.com/fluture-js/Fluture#casting-futures'
);
}
function invalidVersion(m, x){
return (
'The Future was created by ' + (x < version ? 'an older' : 'a newer')
+ ' version of ' + namespace + '. '
+ 'This means that one of the sources which creates Futures is outdated. '
+ 'Update this source, or transform its created Futures to be compatible.'
+ '\n See: https://github.com/fluture-js/Fluture#casting-futures'
);
}
function invalidFuture(desc, m, s){
var id = sanctuaryTypeIdentifiers.parse(sanctuaryTypeIdentifiers(m));
var info = id.name === name ? '\n' + (
id.namespace !== namespace ? invalidNamespace(m, id.namespace)
: id.version !== version ? invalidVersion(m, id.version)
: 'Nothing seems wrong. Contact the Fluture maintainers.') : '';
return typeError(
desc + ' to be a valid Future.' + info + '\n' +
' Actual: ' + sanctuaryShow(m) + ' :: ' + id.name + (s || '')
);
}
function invalidFutureArgument(it, at, m, s){
return invalidFuture(it + '() expects its ' + ordinal[at] + ' argument', m, s);
}
function ensureError(value, fn){
var message;
try{
if(value instanceof Error) return value;
message = 'A Non-Error was thrown from a Future: ' + sanctuaryShow(value);
}catch (_){
message = 'Something was thrown from a Future, but it could not be converted to String';
}
var e = error(message);
captureStackTrace(e, fn);
return e;
}
function assignUnenumerable(o, prop, value){
Object.defineProperty(o, prop, {value: value, writable: true, configurable: true});
}
function wrapException(caught, callingFuture){
var origin = ensureError(caught, wrapException);
var context = cat(origin.context || nil, callingFuture.context);
var e = error(origin.message);
assignUnenumerable(e, 'future', origin.future || callingFuture);
assignUnenumerable(e, 'reason', origin.reason || origin);
assignUnenumerable(e, 'stack', e.reason.stack);
return withExtraContext(e, context);
}
function withExtraContext(e, context){
assignUnenumerable(e, 'context', context);
assignUnenumerable(e, 'stack', e.stack + contextToStackTrace(context));
return e;
}
function contextToStackTrace(context){
var stack = '', tail = context;
while(tail !== nil){
stack = stack + '\n' + tail.head.stack;
tail = tail.tail;
}
return stack;
}
function isFunction(f){
return typeof f === 'function';
}
function isThenable(m){
return m instanceof Promise || m != null && isFunction(m.then);
}
function isBoolean(f){
return typeof f === 'boolean';
}
function isNumber(f){
return typeof f === 'number';
}
function isUnsigned(n){
return (n === Infinity || isNumber(n) && n > 0 && n % 1 === 0);
}
function isObject(o){
return o !== null && typeof o === 'object';
}
function isIterator(i){
return isObject(i) && isFunction(i.next);
}
function isArray(x){
return Array.isArray(x);
}
function hasMethod(method, x){
return x != null && isFunction(x[method]);
}
function isFunctor(x){
return hasMethod(FL.map, x);
}
function isAlt(x){
return isFunctor(x) && hasMethod(FL.alt, x);
}
function isApply(x){
return isFunctor(x) && hasMethod(FL.ap, x);
}
function isBifunctor(x){
return isFunctor(x) && hasMethod(FL.bimap, x);
}
function isChain(x){
return isApply(x) && hasMethod(FL.chain, x);
}
function Next(x){
return {done: false, value: x};
}
function Done(x){
return {done: true, value: x};
}
function isIteration(x){
return isObject(x) && isBoolean(x.done);
}
/*eslint no-cond-assign:0, no-constant-condition:0 */
function alwaysTrue(){
return true;
}
function getArgs(it){
var args = new Array(it.arity);
for(var i = 1; i <= it.arity; i++){
args[i - 1] = it['$' + String(i)];
}
return args;
}
function showArg(arg){
return ' (' + sanctuaryShow(arg) + ')';
}
var any = {pred: alwaysTrue, error: invalidArgumentOf('be anything')};
var func = {pred: isFunction, error: invalidArgumentOf('be a Function')};
var future = {pred: isFuture, error: invalidFutureArgument};
var positiveInteger = {pred: isUnsigned, error: invalidArgumentOf('be a positive Integer')};
function application(n, f, type, args, prev){
if(args.length < 2 && type.pred(args[0])) return captureApplicationContext(prev, n, f);
var e = args.length > 1 ? invalidArity(f, args) : type.error(f.name, n - 1, args[0]);
captureStackTrace(e, f);
throw withExtraContext(e, prev);
}
function application1(f, type, args){
return application(1, f, type, args, nil);
}
function Future(computation){
var context = application1(Future, func, arguments);
return new Computation(context, computation);
}
function isFuture(x){
return x instanceof Future || sanctuaryTypeIdentifiers(x) === $$type$1;
}
// Compliance with sanctuary-type-identifiers versions 1 and 2.
// To prevent sanctuary-type-identifiers version 3 from identifying 'Future'
// as being of the type denoted by $$type, we ensure that
// Future.constructor.prototype is equal to Future.
Future['@@type'] = $$type$1;
Future.constructor = {prototype: Future};
Future[FL.of] = resolve;
Future[FL.chainRec] = chainRec;
Future.prototype['@@type'] = $$type$1;
Future.prototype['@@show'] = function Future$show(){
return this.toString();
};
Future.prototype.pipe = function Future$pipe(f){
if(!isFunction(f)) throw invalidArgument('Future#pipe', 0, 'be a Function', f);
return f(this);
};
Future.prototype[FL.ap] = function Future$FL$ap(other){
var context = captureContext(nil, 'a Fantasy Land dispatch to ap', Future$FL$ap);
return other._transform(new ApTransformation(context, this));
};
Future.prototype[FL.map] = function Future$FL$map(mapper){
var context = captureContext(nil, 'a Fantasy Land dispatch to map', Future$FL$map);
return this._transform(new MapTransformation(context, mapper));
};
Future.prototype[FL.bimap] = function Future$FL$bimap(lmapper, rmapper){
var context = captureContext(nil, 'a Fantasy Land dispatch to bimap', Future$FL$bimap);
return this._transform(new BimapTransformation(context, lmapper, rmapper));
};
Future.prototype[FL.chain] = function Future$FL$chain(mapper){
var context = captureContext(nil, 'a Fantasy Land dispatch to chain', Future$FL$chain);
return this._transform(new ChainTransformation(context, mapper));
};
Future.prototype[FL.alt] = function Future$FL$alt(other){
var context = captureContext(nil, 'a Fantasy Land dispatch to alt', Future$FL$alt);
return this._transform(new AltTransformation(context, other));
};
Future.prototype.extractLeft = function Future$extractLeft(){
return [];
};
Future.prototype.extractRight = function Future$extractRight(){
return [];
};
Future.prototype._transform = function Future$transform(transformation){
return new Transformer(transformation.context, this, cons(transformation, nil));
};
Future.prototype.isTransformer = false;
Future.prototype.context = nil;
Future.prototype.arity = 0;
Future.prototype.name = 'future';
Future.prototype.toString = function Future$toString(){
return this.name + getArgs(this).map(showArg).join('');
};
Future.prototype.toJSON = function Future$toJSON(){
return {$: $$type$1, kind: 'interpreter', type: this.name, args: getArgs(this)};
};
function createInterpreter(arity, name, interpret){
var Interpreter = function(context, $1, $2, $3){
this.context = context;
this.$1 = $1;
this.$2 = $2;
this.$3 = $3;
};
Interpreter.prototype = Object.create(Future.prototype);
Interpreter.prototype.arity = arity;
Interpreter.prototype.name = name;
Interpreter.prototype._interpret = interpret;
return Interpreter;
}
var Computation =
createInterpreter(1, 'Future', function Computation$interpret(rec, rej, res){
var computation = this.$1, open = false, cancel = noop, cont = function(){ open = true; };
try{
cancel = computation(function Computation$rej(x){
cont = function Computation$rej$cont(){
open = false;
rej(x);
};
if(open){
cont();
}
}, function Computation$res(x){
cont = function Computation$res$cont(){
open = false;
res(x);
};
if(open){
cont();
}
});
}catch(e){
rec(wrapException(e, this));
return noop;
}
if(!(isFunction(cancel) && cancel.length === 0)){
rec(wrapException(typeError(
'The computation was expected to return a nullary cancellation function\n' +
' Actual: ' + sanctuaryShow(cancel)
), this));
return noop;
}
cont();
return function Computation$cancel(){
if(open){
open = false;
cancel && cancel();
}
};
});
var Never = createInterpreter(0, 'never', function Never$interpret(){
return noop;
});
Never.prototype._isNever = true;
var never = new Never(nil);
function isNever(x){
return isFuture(x) && x._isNever === true;
}
var Crash = createInterpreter(1, 'crash', function Crash$interpret(rec){
rec(this.$1);
return noop;
});
function crash(x){
return new Crash(application1(crash, any, arguments), x);
}
var Reject = createInterpreter(1, 'reject', function Reject$interpret(rec, rej){
rej(this.$1);
return noop;
});
Reject.prototype.extractLeft = function Reject$extractLeft(){
return [this.$1];
};
function reject(x){
return new Reject(application1(reject, any, arguments), x);
}
var Resolve = createInterpreter(1, 'resolve', function Resolve$interpret(rec, rej, res){
res(this.$1);
return noop;
});
Resolve.prototype.extractRight = function Resolve$extractRight(){
return [this.$1];
};
function resolve(x){
return new Resolve(application1(resolve, any, arguments), x);
}
//Note: This function is not curried because it's only used to satisfy the
// Fantasy Land ChainRec specification.
function chainRec(step, init){
return resolve(Next(init))._transform(new ChainTransformation(nil, function chainRec$recur(o){
return o.done ?
resolve(o.value) :
step(Next, Done, o.value)._transform(new ChainTransformation(nil, chainRec$recur));
}));
}
var Transformer =
createInterpreter(2, 'transform', function Transformer$interpret(rec, rej, res){
//These are the cold, and hot, transformation stacks. The cold actions are those that
//have yet to run parallel computations, and hot are those that have.
var cold = nil, hot = nil;
//These combined variables define our current state.
// future = the future we are currently forking
// transformation = the transformation to be informed when the future settles
// cancel = the cancel function of the current future
// settled = a boolean indicating whether a new tick should start
// async = a boolean indicating whether we are awaiting a result asynchronously
var future, transformation, cancel = noop, settled, async = true, it;
//Takes a transformation from the top of the hot stack and returns it.
function nextHot(){
var x = hot.head;
hot = hot.tail;
return x;
}
//Takes a transformation from the top of the cold stack and returns it.
function nextCold(){
var x = cold.head;
cold = cold.tail;
return x;
}
//This function is called with a future to use in the next tick.
//Here we "flatten" the actions of another Sequence into our own actions,
//this is the magic that allows for infinitely stack safe recursion because
//actions like ChainAction will return a new Sequence.
//If we settled asynchronously, we call drain() directly to run the next tick.
function settle(m){
settled = true;
future = m;
if(future.isTransformer){
var tail = future.$2;
while(!isNil(tail)){
cold = cons(tail.head, cold);
tail = tail.tail;
}
future = future.$1;
}
if(async) drain();
}
//This function serves as a rejection handler for our current future.
//It will tell the current transformation that the future rejected, and it will
//settle the current tick with the transformation's answer to that.
function rejected(x){
settle(transformation.rejected(x));
}
//This function serves as a resolution handler for our current future.
//It will tell the current transformation that the future resolved, and it will
//settle the current tick with the transformation's answer to that.
function resolved(x){
settle(transformation.resolved(x));
}
//This function is passed into actions when they are "warmed up".
//If the transformation decides that it has its result, without the need to await
//anything else, then it can call this function to force "early termination".
//When early termination occurs, all actions which were stacked prior to the
//terminator will be skipped. If they were already hot, they will also be
//sent a cancel signal so they can cancel their own concurrent computations,
//as their results are no longer needed.
function early(m, terminator){
cancel();
cold = nil;
if(async && transformation !== terminator){
transformation.cancel();
while((it = nextHot()) && it !== terminator) it.cancel();
}
settle(m);
}
//This will cancel the current Future, the current transformation, and all stacked hot actions.
function Sequence$cancel(){
cancel();
transformation && transformation.cancel();
while(it = nextHot()) it.cancel();
}
//This function is called when an exception is caught.
function exception(e){
Sequence$cancel();
settled = true;
cold = hot = nil;
var error = wrapException(e, future);
future = never;
rec(error);
}
//This function serves to kickstart concurrent computations.
//Takes all actions from the cold stack in reverse order, and calls run() on
//each of them, passing them the "early" function. If any of them settles (by
//calling early()), we abort. After warming up all actions in the cold queue,
//we warm up the current transformation as well.
function warmupActions(){
cold = reverse(cold);
while(cold !== nil){
it = cold.head.run(early);
if(settled) return;
hot = cons(it, hot);
cold = cold.tail;
}
transformation = transformation.run(early);
}
//This function represents our main execution loop. By "tick", we've been
//referring to the execution of one iteration in the while-loop below.
function drain(){
async = false;
while(true){
settled = false;
if(transformation = nextCold()){
cancel = future._interpret(exception, rejected, resolved);
if(!settled) warmupActions();
}else if(transformation = nextHot()){
cancel = future._interpret(exception, rejected, resolved);
}else break;
if(settled) continue;
async = true;
return;
}
cancel = future._interpret(exception, rej, res);
}
//Start the execution loop.
settle(this);
//Return the cancellation function.
return Sequence$cancel;
});
Transformer.prototype.isTransformer = true;
Transformer.prototype._transform = function Transformer$_transform(transformation){
return new Transformer(transformation.context, this.$1, cons(transformation, this.$2));
};
Transformer.prototype.toString = function Transformer$toString(){
return toArray(reverse(this.$2)).reduce(function(str, action){
return action.name + getArgs(action).map(showArg).join('') + ' (' + str + ')';
}, this.$1.toString());
};
function BaseTransformation$rejected(x){
this.cancel();
return new Reject(this.context, x);
}
function BaseTransformation$resolved(x){
this.cancel();
return new Resolve(this.context, x);
}
function BaseTransformation$toJSON(){
return {$: $$type$1, kind: 'transformation', type: this.name, args: getArgs(this)};
}
var BaseTransformation = {
rejected: BaseTransformation$rejected,
resolved: BaseTransformation$resolved,
run: moop,
cancel: noop,
context: nil,
arity: 0,
name: 'transform',
toJSON: BaseTransformation$toJSON
};
function wrapHandler(handler){
return function transformationHandler(x){
var m;
try{
m = handler.call(this, x);
}catch(e){
return new Crash(this.context, e);
}
if(isFuture(m)){
return m;
}
return new Crash(this.context, invalidFuture(
this.name + ' expects the return value from the function it\'s given', m,
'\n When called with: ' + sanctuaryShow(x)
));
};
}
function createTransformation(arity, name, prototype){
var Transformation = function(context, $1, $2){
this.context = context;
this.$1 = $1;
this.$2 = $2;
};
Transformation.prototype = Object.create(BaseTransformation);
Transformation.prototype.arity = arity;
Transformation.prototype.name = name;
if(typeof prototype.rejected === 'function'){
Transformation.prototype.rejected = wrapHandler(prototype.rejected);
}
if(typeof prototype.resolved === 'function'){
Transformation.prototype.resolved = wrapHandler(prototype.resolved);
}
if(typeof prototype.run === 'function'){
Transformation.prototype.run = prototype.run;
}
return Transformation;
}
var ApTransformation = createTransformation(1, 'ap', {
resolved: function ApTransformation$resolved(f){
if(isFunction(f)) return this.$1._transform(new MapTransformation(this.context, f));
throw typeError(
'ap expects the second Future to resolve to a Function\n' +
' Actual: ' + sanctuaryShow(f)
);
}
});
var AltTransformation = createTransformation(1, 'alt', {
rejected: function AltTransformation$rejected(){ return this.$1 }
});
var MapTransformation = createTransformation(1, 'map', {
resolved: function MapTransformation$resolved(x){
return new Resolve(this.context, call(this.$1, x));
}
});
var BimapTransformation = createTransformation(2, 'bimap', {
rejected: function BimapTransformation$rejected(x){
return new Reject(this.context, call(this.$1, x));
},
resolved: function BimapTransformation$resolved(x){
return new Resolve(this.context, call(this.$2, x));
}
});
var ChainTransformation = createTransformation(1, 'chain', {
resolved: function ChainTransformation$resolved(x){ return call(this.$1, x) }
});
var After = createInterpreter(2, 'after', function After$interpret(rec, rej, res){
var id = setTimeout(res, this.$1, this.$2);
return function After$cancel(){ clearTimeout(id); };
});
After.prototype.extractRight = function After$extractRight(){
return [this.$2];
};
function alwaysNever$1(_){
return never;
}
function after(time){
var context1 = application1(after, positiveInteger, arguments);
return time === Infinity ? alwaysNever$1 : (function after(value){
var context2 = application(2, after, any, arguments, context1);
return new After(context2, time, value);
});
}
var alternative = {pred: isAlt, error: invalidArgumentOf('have Alt implemented')};
function alt(left){
if(isFuture(left)){
var context1 = application1(alt, future, arguments);
return function alt(right){
var context2 = application(2, alt, future, arguments, context1);
return right._transform(new AltTransformation(context2, left));
};
}
var context = application1(alt, alternative, arguments);
return function alt(right){
application(2, alt, alternative, arguments, context);
return left[FL.alt](right);
};
}
var AndTransformation = createTransformation(1, 'and', {
resolved: function AndTransformation$resolved(){ return this.$1 }
});
function and(left){
var context1 = application1(and, future, arguments);
return function and(right){
var context2 = application(2, and, future, arguments, context1);
return right._transform(new AndTransformation(context2, left));
};
}
var apply = {pred: isApply, error: invalidArgumentOf('have Apply implemented')};
function ap(mx){
if(isFuture(mx)){
var context1 = application1(ap, future, arguments);
return function ap(mf){
var context2 = application(2, ap, future, arguments, context1);
return mf._transform(new ApTransformation(context2, mx));
};
}
var context = application1(ap, apply, arguments);
return function ap(mf){
application(2, ap, apply, arguments, context);
return mx[FL.ap](mf);
};
}
function invalidPromise(p, f, a){
return typeError(
'encaseP() expects the function it\'s given to return a Promise/Thenable'
+ '\n Actual: ' + sanctuaryShow(p) + '\n From calling: ' + sanctuaryShow(f)
+ '\n With: ' + sanctuaryShow(a)
);
}
var EncaseP = createInterpreter(2, 'encaseP', function EncaseP$interpret(rec, rej, res){
var open = true, fn = this.$1, arg = this.$2, p;
try{
p = fn(arg);
}catch(e){
rec(wrapException(e, this));
return noop;
}
if(!isThenable(p)){
rec(wrapException(invalidPromise(p, fn, arg), this));
return noop;
}
p.then(function EncaseP$res(x){
if(open){
open = false;
res(x);
}
}, function EncaseP$rej(x){
if(open){
open = false;
rej(x);
}
});
return function EncaseP$cancel(){ open = false; };
});
function encaseP(f){
var context1 = application1(encaseP, func, arguments);
return function encaseP(x){
var context2 = application(2, encaseP, any, arguments, context1);
return new EncaseP(context2, f, x);
};
}
function attemptP(_){
return encaseP.apply(this, arguments)(undefined);
}
var Encase = createInterpreter(2, 'encase', function Encase$interpret(rec, rej, res){
var fn = this.$1, r;
try{ r = fn(this.$2); }catch(e){ rej(e); return noop }
res(r);
return noop;
});
function encase(f){
var context1 = application1(encase, func, arguments);
return function encase(x){
var context2 = application(2, encase, any, arguments, context1);
return new Encase(context2, f, x);
};
}
function attempt(_){
return encase.apply(this, arguments)(undefined);
}
var bifunctor = {pred: isBifunctor, error: invalidArgumentOf('have Bifunctor implemented')};
function bimap(f){
var context1 = application1(bimap, func, arguments);
return function bimap(g){
var context2 = application(2, bimap, func, arguments, context1);
return function bimap(m){
var context3 = application(3, bimap, bifunctor, arguments, context2);
return isFuture(m) ?
m._transform(new BimapTransformation(context3, f, g)) :
m[FL.bimap](f, g);
};
};
}
var BichainTransformation = createTransformation(2, 'bichain', {
rejected: function BichainTransformation$rejected(x){ return call(this.$1, x) },
resolved: function BichainTransformation$resolved(x){ return call(this.$2, x) }
});
function bichain(f){
var context1 = application1(bichain, func, arguments);
return function bichain(g){
var context2 = application(2, bichain, func, arguments, context1);
return function bichain(m){
var context3 = application(3, bichain, future, arguments, context2);
return m._transform(new BichainTransformation(context3, f, g));
};
};
}
function Eager(future){
var _this = this;
_this.rec = noop;
_this.rej = noop;
_this.res = noop;
_this.crashed = false;
_this.rejected = false;
_this.resolved = false;
_this.value = null;
_this.cancel = future._interpret(function Eager$crash(x){
_this.value = x;
_this.crashed = true;
_this.cancel = noop;
_this.rec(x);
}, function Eager$reject(x){
_this.value = x;
_this.rejected = true;
_this.cancel = noop;
_this.rej(x);
}, function Eager$resolve(x){
_this.value = x;
_this.resolved = true;
_this.cancel = noop;
_this.res(x);
});
}
Eager.prototype = Object.create(Future.prototype);
Eager.prototype._interpret = function Eager$interpret(rec, rej, res){
if(this.crashed) rec(this.value);
else if(this.rejected) rej(this.value);
else if(this.resolved) res(this.value);
else {
this.rec = rec;
this.rej = rej;
this.res = res;
}
return this.cancel;
};
function earlyCrash(early, x){
early(crash(x));
}
function earlyReject(early, x){
early(reject(x));
}
function earlyResolve(early, x){
early(resolve(x));
}
function createParallelTransformation(name, rec, rej, res, prototype){
var ParallelTransformation = createTransformation(1, name, Object.assign({
run: function Parallel$run(early){
var eager = new Eager(this.$1);
var transformation = new ParallelTransformation(this.context, eager);
function Parallel$early(m){ early(m, transformation); }
transformation.cancel = eager._interpret(
function Parallel$rec(x){ rec(Parallel$early, x); },
function Parallel$rej(x){ rej(Parallel$early, x); },
function Parallel$res(x){ res(Parallel$early, x); }
);
return transformation;
}
}, prototype));
return ParallelTransformation;
}
var PairTransformation = createTransformation(1, 'pair', {
resolved: function PairTransformation$resolved(x){
return new Resolve(this.context, [x, this.$1]);
}
});
var BothTransformation =
createParallelTransformation('both', earlyCrash, earlyReject, noop, {
resolved: function BothTransformation$resolved(x){
return this.$1._transform(new PairTransformation(this.context, x));
}
});
function both(left){
var context1 = application1(both, future, arguments);
return function both(right){
var context2 = application(2, both, future, arguments, context1);
return right._transform(new BothTransformation(context2, left));
};
}
var Cold = 0;
var Pending = 1;
var Crashed = 2;
var Rejected = 3;
var Resolved = 4;
function Queued(rec, rej, res){
this[Crashed] = rec;
this[Rejected] = rej;
this[Resolved] = res;
}
var Cache = createInterpreter(1, 'cache', function Cache$interpret(rec, rej, res){
var cancel = noop;
switch(this._state){
/* c8 ignore next 4 */
case Pending: cancel = this._addToQueue(rec, rej, res); break;
case Crashed: rec(this._value); break;
case Rejected: rej(this._value); break;
case Resolved: res(this._value); break;
default:
this._queue = [];
cancel = this._addToQueue(rec, rej, res);
this.run();
}
return cancel;
});
Cache.prototype._cancel = noop;
Cache.prototype._queue = null;
Cache.prototype._queued = 0;
Cache.prototype._value = undefined;
Cache.prototype._state = Cold;
Cache.prototype.extractLeft = function Cache$extractLeft(){
return this._state === Rejected ? [this._value] : [];
};
Cache.prototype.extractRight = function Cache$extractRight(){
return this._state === Resolved ? [this._value] : [];
};
Cache.prototype._addToQueue = function Cache$addToQueue(rec, rej, res){
var _this = this;
if(_this._state > Pending) return noop;
var i = _this._queue.push(new Queued(rec, rej, res)) - 1;
_this._queued = _this._queued + 1;
return function Cache$removeFromQueue(){
if(_this._state > Pending) return;
_this._queue[i] = undefined;
_this._queued = _this._queued - 1;
if(_this._queued === 0) _this.reset();
};
};
Cache.prototype._drainQueue = function Cache$drainQueue(){
if(this._state <= Pending) return;
if(this._queued === 0) return;
var queue = this._queue;
var length = queue.length;
var state = this._state;
var value = this._value;
for(var i = 0; i < length; i++){
queue[i] && queue[i][state](value);
queue[i] = undefined;
}
this._queue = undefined;
this._queued = 0;
};
Cache.prototype.crash = function Cache$crash(error){
if(this._state > Pending) return;
this._value = error;
this._state = Crashed;
this._drainQueue();
};
Cache.prototype.reject = function Cache$reject(reason){
if(this._state > Pending) return;
this._value = reason;
this._state = Rejected;
this._drainQueue();
};
Cache.prototype.resolve = function Cache$resolve(value){
if(this._state > Pending) return;
this._value = value;
this._state = Resolved;
this._drainQueue();
};
Cache.prototype.run = function Cache$run(){
var _this = this;
if(_this._state > Cold) return;
_this._state = Pending;
_this._cancel = _this.$1._interpret(
function Cache$fork$rec(x){ _this.crash(x); },
function Cache$fork$rej(x){ _this.reject(x); },
function Cache$fork$res(x){ _this.resolve(x); }
);
};
Cache.prototype.reset = function Cache$reset(){
if(this._state === Cold) return;
if(this._state === Pending) this._cancel();
this._cancel = noop;
this._queue = [];
this._queued = 0;
this._value = undefined;
this._state = Cold;
};
function cache(m){
return new Cache(application1(cache, future, arguments), m);
}
var ChainRejTransformation = createTransformation(1, 'chainRej', {
rejected: function ChainRejTransformation$rejected(x){ return call(this.$1, x) }
});
function chainRej(f){
var context1 = application1(chainRej, func, arguments);
return function chainRej(m){
var context2 = application(2, chainRej, future, arguments, context1);
return m._transform(new ChainRejTransformation(context2, f));
};
}
var monad = {pred: isChain, error: invalidArgumentOf('have Chain implemented')};
function chain(f){
var context1 = application1(chain, func, arguments);
return function chain(m){
var context2 = application(2, chain, monad, arguments, context1);
return isFuture(m) ?
m._transform(new ChainTransformation(context2, f)) :
m[FL.chain](f);
};
}
function done(callback){
var context1 = application1(done, func, arguments);
function done$res(x){
callback(null, x);
}
return function done(m){
application(2, done, future, arguments, context1);
return m._interpret(raise, callback, done$res);
};
}
function extractLeft(m){
application1(extractLeft, future, arguments);
return m.extractLeft();
}
function extractRight(m){
application1(extractRight, future, arguments);
return m.extractRight();
}
var CoalesceTransformation = createTransformation(2, 'coalesce', {
rejected: function CoalesceTransformation$rejected(x){
return new Resolve(this.context, call(this.$1, x));
},
resolved: function CoalesceTransformation$resolved(x){
return new Resolve(this.context, call(this.$2, x));
}
});
function coalesce(f){
var context1 = application1(coalesce, func, arguments);
return function coalesce(g){
var context2 = application(2, coalesce, func, arguments, context1);
return function coalesce(m){
var context3 = application(3, coalesce, future, arguments, context2);
return m._transform(new CoalesceTransformation(context3, f, g));
};
};
}
function forkCatch(f){
var context1 = application1(forkCatch, func, arguments);
return function forkCatch(g){
var context2 = application(2, forkCatch, func, arguments, context1);
return function forkCatch(h){
var context3 = application(3, forkCatch, func, arguments, context2);
return function forkCatch(m){
application(4, forkCatch, future, arguments, context3);
return m._interpret(f, g, h);
};
};
};
}
function fork(f){
var context1 = application1(fork, func, arguments);
return function fork(g){
var context2 = application(2, fork, func, arguments, context1);
return function fork(m){
application(3, fork, future, arguments, context2);
return m._interpret(raise, f, g);
};
};
}
var Undetermined = 0;
var Synchronous = 1;
var Asynchronous = 2;
/*eslint consistent-return: 0 */
function invalidIteration(o){
return typeError(
'The iterator did not return a valid iteration from iterator.next()\n' +
' Actual: ' + sanctuaryShow(o)
);
}
function invalidState(x){
return invalidFuture(
'go() expects the value produced by the iterator', x,
'\n Tip: If you\'re using a generator, make sure you always yield a Future'
);
}
var Go = createInterpreter(1, 'go', function Go$interpret(rec, rej, res){
var _this = this, timing = Undetermined, cancel = noop, state, value, iterator;
function crash(e){
rec(wrapException(e, _this));
}
try{
iterator = _this.$1();
}catch(e){
crash(e);
return noop;
}
if(!isIterator(iterator)){
crash(invalidArgument('go', 0, 'return an iterator, maybe you forgot the "*"', iterator));
return noop;
}
function resolved(x){
value = x;
if(timing === Asynchronous) return drain();
timing = Synchronous;
}
function drain(){
//eslint-disable-next-line no-constant-condition
while(true){
try{
state = iterator.next(value);
}catch(e){
return crash(e);
}
if(!isIteration(state)) return crash(invalidIteration(state));
if(state.done) break;
if(!isFuture(state.value)){
return crash(invalidState(state.value));
}
timing = Undetermined;
cancel = state.value._interpret(crash, rej, resolved);
if(timing === Undetermined) return timing = Asynchronous;
}
res(state.value);
}
drain();
return function Go$cancel(){ cancel(); };
});
function go(generator){
return new Go(application1(go, func, arguments), generator);
}
function invalidDisposal(m, f, x){
return invalidFuture(
'hook() expects the return value from the first function it\'s given', m,
'\n From calling: ' + sanctuaryShow(f) + '\n With: ' + sanctuaryShow(x)
);
}
function invalidConsumption(m, f, x){
return invalidFuture(
'hook() expects the return value from the second function it\'s given', m,
'\n From calling: ' + sanctuaryShow(f) + '\n With: ' + sanctuaryShow(x)
);
}
var Hook = createInterpreter(3, 'hook', function Hook$interpret(rec, rej, res){
var _this = this, _acquire = this.$1, _dispose = this.$2, _consume = this.$3;
var cancel, cancelConsume = noop, resource, value, cont = noop;
function Hook$done(){
cont(value);
}
function Hook$rec(x){
rec(wrapException(x, _this));
}
function Hook$dispose(){
var disposal;
try{
disposal = _dispose(resource);
}catch(e){
return Hook$rec(e);
}
if(!isFuture(disposal)){
return Hook$rec(invalidDisposal(disposal, _dispose, resource));
}
cancel = Hook$cancelDisposal;
disposal._interpret(Hook$rec, Hook$disposalRejected, Hook$done);
}
function Hook$cancelConsumption(){
cancelConsume();
Hook$dispose();
Hook$cancelDisposal();
}
function Hook$cancelDisposal(){
cont = noop;
}
function Hook$disposalRejected(x){
Hook$rec(new Error('The disposal Future rejected with ' + sanctuaryShow(x)));
}
function Hook$consumptionException(x){
cont = Hook$rec;
value = x;
Hook$dispose();
}
function Hook$consumptionRejected(x){
cont = rej;
value = x;
Hook$dispose();
}
function Hook$consumptionResolved(x){
cont = res;
value = x;
Hook$dispose();
}
function Hook$consume(x){
resource = x;
var consumption;
try{
consumption = _consume(resource);
}catch(e){
return Hook$consumptionException(e);
}
if(!isFuture(consumption)){
return Hook$consumptionException(invalidConsumption(consumption, _consume, resource));
}
cancel = Hook$cancelConsumption;
cancelConsume = consumption._interpret(
Hook$consumptionException,
Hook$consumptionRejected,
Hook$consumptionResolved
);
}
var cancelAcquire = _acquire._interpret(Hook$rec, rej, Hook$consume);
cancel = cancel || cancelAcquire;
return function Hook$fork$cancel(){
rec = raise;
cancel();
};
});
function hook(acquire){
var context1 = application1(hook, future, arguments);
return function hook(dispose){
var context2 = application(2, hook, func, arguments, context1);
return function hook(consume){
var context3 = application(3, hook, func, arguments, context2);
return new Hook(context3, acquire, dispose, consume);
};
};
}
var LastlyTransformation = createTransformation(1, 'lastly', {
rejected: function LastlyAction$rejected(x){
return this.$1._transform(new AndTransformation(this.context, new Reject(this.context, x)));
},
resolved: function LastlyAction$resolved(x){
return this.$1._transform(new AndTransformation(this.context, new Resolve(this.context, x)));
}
});
function lastly(cleanup){
var context1 = application1(lastly, future, arguments);
return function lastly(program){
var context2 = application(2, lastly, future, arguments, context1);
return program._transform(new LastlyTransformation(context2, cleanup));
};
}
var MapRejTransformation = createTransformation(1, 'mapRej', {
rejected: function MapRejTransformation$rejected(x){
return new Reject(this.context, call(this.$1, x));
}
});
function mapRej(f){
var context1 = application1(mapRej, func, arguments);
return function mapRej(m){
var context2 = application(2, mapRej, future, arguments, context1);
return m._transform(new MapRejTransformation(context2, f));
};
}
var functor = {pred: isFunctor, error: invalidArgumentOf('have Functor implemented')};
function map(f){
var context1 = application1(map, func, arguments);
return function map(m){
var context2 = application(2, map, functor, arguments, context1);
return isFuture(m) ?
m._transform(new MapTransformation(context2, f)) :
m[FL.map](f);
};
}
var Node = createInterpreter(1, 'node', function Node$interpret(rec, rej, res){
function Node$done(err, val){
cont = err ? function EncaseN3$rej(){
open = false;
rej(err);
} : function EncaseN3$res(){
open = false;
res(val);
};
if(open){
cont();
}
}
var open = false, cont = function(){ open = true; };
try{
call(this.$1, Node$done);
}catch(e){
rec(wrapException(e, this));
open = false;
return noop;
}
cont();
return function Node$cancel(){ open = false; };
});
function node(f){
return new Node(application1(node, func, arguments), f);
}
var ParallelApTransformation =
createParallelTransformation('pap', earlyCrash, earlyReject, noop, {
resolved: function ParallelApTransformation$resolved(f){
if(isFunction(f)) return this.$1._transform(new MapTransformation(this.context, f));
throw typeError(
'pap expects the second Future to resolve to a Function\n' +
' Actual: ' + sanctuaryShow(f)
);
}
});
function pap(mx){
var context1 = application1(pap, future, arguments);
return function pap(mf){
var context2 = application(2, pap, future, arguments, context1);
return mf._transform(new ParallelApTransformation(context2, mx));
};
}
function isFutureArray(xs){
if(!isArray(xs)) return false;
for(var i = 0; i < xs.length; i++){
if(!isFuture(xs[i])) return false;
}
return true;
}
var futureArray = {
pred: isFutureArray,
error: invalidArgumentOf('be an Array of valid Futures')
};
var Parallel = createInterpreter(2, 'parallel', function Parallel$interpret(rec, rej, res){
var _this = this, futures = this.$2, length = futures.length;
var max = Math.min(this.$1, length), cancels = new Array(length), out = new Array(length);
var cursor = 0, running = 0, blocked = false, cont = noop;
function Parallel$cancel(){
rec = noop;
rej = noop;
res = noop;
cursor = length;
for(var n = 0; n < length; n++) cancels[n] && cancels[n]();
}
function Parallel$run(idx){
running++;
cancels[idx] = futures[idx]._interpret(function Parallel$rec(e){
cont = rec;
cancels[idx] = noop;
Parallel$cancel();
cont(wrapException(e, _this));
}, function Parallel$rej(reason){
cont = rej;
cancels[idx] = noop;
Parallel$cancel();
cont(reason);
}, function Parallel$res(value){
cancels[idx] = noop;
out[idx] = value;
running--;
if(cursor === length && running === 0) res(out);
else if(blocked) Parallel$drain();
});
}
function Parallel$drain(){
blocked = false;
while(cursor < length && running < max) Parallel$run(cursor++);
blocked = true;
}
Parallel$drain();
return Parallel$cancel;
});
var emptyArray = resolve([]);
function parallel$1(max){
var context1 = application1(parallel$1, positiveInteger, arguments);
return function parallel(ms){
var context2 = application(2, parallel, futureArray, arguments, context1);
return ms.length === 0 ? emptyArray : new Parallel(context2, max, ms);
};
}
var RaceTransformation =
createParallelTransformation('race', earlyCrash, earlyReject, earlyResolve, {});
function race(left){
var context1 = application1(race, future, arguments);
return function race(right){
var context2 = application(2, race, future, arguments, context1);
return right._transform(new RaceTransformation(context2, left));
};
}
function ConcurrentFuture (sequential){
this.sequential = sequential;
}
ConcurrentFuture.prototype = Object.create(Par.prototype);
function Par (sequential){
if(!isFuture(sequential)) throw invalidFutureArgument(Par.name, 0, sequential);
return new ConcurrentFuture(sequential);
}
var $$type = namespace + '/ConcurrentFuture@' + version;
var zeroInstance = new ConcurrentFuture(never);
// Compliance with sanctuary-type-identifiers versions 1 and 2.
// To prevent sanctuary-type-identifiers version 3 from identifying
// 'Par' as being of the type denoted by $$type, we ensure that
// Par.constructor.prototype is equal to Par.
Par['@@type'] = $$type;
Par.constructor = {prototype: Par};
Par[FL.of] = function Par$of(x){
return new ConcurrentFuture(resolve(x));
};
Par[FL.zero] = function Par$zero(){
return zeroInstance;
};
Par.prototype['@@type'] = $$type;
Par.prototype['@@show'] = function Par$show(){
return this.toString();
};
Par.prototype.toString = function Par$toString(){
return 'Par (' + this.sequential.toString() + ')';
};
Par.prototype[FL.map] = function Par$FL$map(f){
var context = captureContext(
nil,
'a Fantasy Land dispatch to map via ConcurrentFuture',
Par$FL$map
);
return new ConcurrentFuture(this.sequential._transform(new MapTransformation(context, f)));
};
Par.prototype[FL.ap] = function Par$FL$ap(other){
var context = captureContext(
nil,
'a Fantasy Land dispatch to ap via ConcurrentFuture',
Par$FL$ap
);
return new ConcurrentFuture(other.sequential._transform(
new ParallelApTransformation(context, this.sequential)
));
};
Par.prototype[FL.alt] = function Par$FL$alt(other){
var context = captureContext(
nil,
'a Fantasy Land dispatch to alt via ConcurrentFuture',
Par$FL$alt
);
return new ConcurrentFuture(other.sequential._transform(
new RaceTransformation(context, this.sequential)
));
};
function isParallel(x){
return x instanceof ConcurrentFuture || sanctuaryTypeIdentifiers(x) === $$type;
}
function promise(m){
application1(promise, future, arguments);
return new Promise(function promise$computation(res, rej){
m._interpret(rej, rej, res);
});
}
var RejectAfter =
createInterpreter(2, 'rejectAfter', function RejectAfter$interpret(rec, rej){
var id = setTimeout(rej, this.$1, this.$2);
return function RejectAfter$cancel(){ clearTimeout(id); };
});
RejectAfter.prototype.extractLeft = function RejectAfter$extractLeft(){
return [this.$2];
};
function alwaysNever(_){
return never;
}
function rejectAfter(time){
var context1 = application1(rejectAfter, positiveInteger, arguments);
return time === Infinity ? alwaysNever : (function rejectAfter(value){
var context2 = application(2, rejectAfter, any, arguments, context1);
return new RejectAfter(context2, time, value);
});
}
var parallel = {pred: isParallel, error: invalidArgumentOf('be a ConcurrentFuture')};
function seq(par){
application1(seq, parallel, arguments);
return par.sequential;
}
var SwapTransformation = createTransformation(0, 'swap', {
resolved: function SwapTransformation$resolved(x){
return new Reject(this.context, x);
},
rejected: function SwapTransformation$rejected(x){
return new Resolve(this.context, x);
}
});
function swap(m){
var context = application1(swap, future, arguments);
return m._transform(new SwapTransformation(context));
}
function value(res){
var context1 = application1(value, func, arguments);
return function value(m){
application(2, value, future, arguments, context1);
function value$rej(x){
raise(error(
'Future#value was called on a rejected Future\n' +
' Rejection: ' + sanctuaryShow(x) + '\n' +
' Future: ' + sanctuaryShow(m)
));
}
return m._interpret(raise, value$rej, res);
};
}
export default Future;
export { Future, Par, after, alt, and, ap, attempt, attemptP, bichain, bimap, both, cache, chain, chainRej, coalesce, debugMode, done, encase, encaseP, extractLeft, extractRight, fork, forkCatch, go, hook, isFuture, isNever, lastly, map, mapRej, never, node, pap, parallel$1 as parallel, promise, race, reject, rejectAfter, resolve, seq, swap, value };
/** Fluture license
The MIT License (MIT)
Copyright (c) 2020 Aldwin Vlasblom
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/** sanctuary-show license
The MIT License (MIT)
Copyright (c) 2020 Sanctuary
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/** sanctuary-type-identifiers license
The MIT License (MIT)
Copyright (c) 2019 Sanctuary
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
================================================
FILE: index.cjs.js
================================================
import * as Fluture from './index.js';
export default Object.assign(Fluture.Future, Fluture);
================================================
FILE: index.d.ts
================================================
/// <reference lib="es2015.generator" />
/// <reference lib="es2015.iterable" />
export interface RecoverFunction {
(exception: Error): void
}
export interface RejectFunction<L> {
(error: L): void
}
export interface ResolveFunction<R> {
(value: R): void
}
export interface Cancel {
(): void
}
export interface Nodeback<E, R> {
(err: E | null, value?: R): void
}
declare const $T: unique symbol
export interface Functor<A> {
[$T]: unknown
'fantasy-land/map'<B extends this[typeof $T]>(mapper: (value: A) => B): Functor<B>
}
type Mapped<F extends Funct
gitextract_iludrmak/
├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .github/
│ ├── FUNDING.yml
│ ├── dependabot.yml
│ └── workflows/
│ └── test.yml
├── .gitignore
├── .npmrc
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── bench/
│ ├── .eslintrc.json
│ ├── .npmrc
│ ├── README.md
│ ├── fluture.js
│ ├── folktale.js
│ ├── package.json
│ └── promise.js
├── dist/
│ ├── bundle.js
│ └── module.js
├── index.cjs.js
├── index.d.ts
├── index.js
├── package.json
├── rollup.config.dist.js
├── rollup.config.js
├── scripts/
│ ├── bench.js
│ ├── distribute
│ ├── test-esm
│ └── test-mem
├── src/
│ ├── after.js
│ ├── alt.js
│ ├── and.js
│ ├── ap.js
│ ├── attempt-p.js
│ ├── attempt.js
│ ├── bichain.js
│ ├── bimap.js
│ ├── both.js
│ ├── cache.js
│ ├── chain-rej.js
│ ├── chain.js
│ ├── coalesce.js
│ ├── done.js
│ ├── encase-p.js
│ ├── encase.js
│ ├── extract-left.js
│ ├── extract-right.js
│ ├── fork-catch.js
│ ├── fork.js
│ ├── future.js
│ ├── go.js
│ ├── hook.js
│ ├── internal/
│ │ ├── const.js
│ │ ├── debug.js
│ │ ├── error.js
│ │ ├── iteration.js
│ │ ├── list.js
│ │ ├── parallel.js
│ │ ├── predicates.js
│ │ ├── timing.js
│ │ └── utils.js
│ ├── lastly.js
│ ├── map-rej.js
│ ├── map.js
│ ├── node.js
│ ├── pap.js
│ ├── par.js
│ ├── parallel.js
│ ├── promise.js
│ ├── race.js
│ ├── reject-after.js
│ ├── seq.js
│ ├── swap.js
│ └── value.js
└── test/
├── arbitraries.js
├── assertions.js
├── build/
│ ├── main.js
│ └── require.js
├── integration/
│ └── main.js
├── prop/
│ ├── 0.algebra.js
│ ├── 0.fantasy-land.js
│ ├── 1.fantasy-libs.js
│ └── 2.arbitrary.js
├── types/
│ └── map.test-d.ts
├── unit/
│ ├── 0.debug.js
│ ├── 0.error.js
│ ├── 0.iteration.js
│ ├── 0.list.js
│ ├── 0.predicates.js
│ ├── 0.utils.js
│ ├── 1.future.js
│ ├── 1.is-future.js
│ ├── 1.is-never.js
│ ├── 1.never.js
│ ├── 1.pipe.js
│ ├── 2.done.js
│ ├── 2.extract-left.js
│ ├── 2.extract-right.js
│ ├── 2.fork-catch.js
│ ├── 2.fork.js
│ ├── 2.promise.js
│ ├── 2.value.js
│ ├── 3.after.js
│ ├── 3.attempt-p.js
│ ├── 3.attempt.js
│ ├── 3.cache.js
│ ├── 3.crash.js
│ ├── 3.encase-p.js
│ ├── 3.encase.js
│ ├── 3.go.js
│ ├── 3.hook.js
│ ├── 3.node.js
│ ├── 3.parallel.js
│ ├── 3.reject-after.js
│ ├── 3.reject.js
│ ├── 3.resolve.js
│ ├── 4.alt.js
│ ├── 4.and.js
│ ├── 4.ap.js
│ ├── 4.bichain.js
│ ├── 4.bimap.js
│ ├── 4.both.js
│ ├── 4.chain-rej.js
│ ├── 4.chain.js
│ ├── 4.coalesce.js
│ ├── 4.lastly.js
│ ├── 4.map-rej.js
│ ├── 4.map.js
│ ├── 4.pap.js
│ ├── 4.race.js
│ ├── 4.swap.js
│ ├── 5.chain-rec.js
│ ├── 5.par.js
│ └── 5.seq.js
└── util/
├── futures.js
├── props.js
└── util.js
SYMBOL INDEX (497 symbols across 59 files)
FILE: dist/bundle.js
function createCommonjsModule (line 8) | function createCommonjsModule(fn) {
function type (line 137) | function type(x) {
function List (line 204) | function List(head, tail){
function isNil (line 216) | function isNil(list){
function cons (line 222) | function cons(head, tail){
function reverse (line 228) | function reverse(xs){
function cat (line 239) | function cat(xs, ys){
function toArray (line 250) | function toArray(xs){
function debugMode (line 263) | function debugMode(debug){
function debugHandleNone (line 267) | function debugHandleNone(x){
function debugHandleAll (line 271) | function debugHandleAll(x, fn, a, b, c){
function debug (line 275) | function debug(x, fn, a, b, c){
function captureContext (line 279) | function captureContext(previous, tag, fn){
function debugCaptureContext (line 283) | function debugCaptureContext(previous, tag, fn){
function captureApplicationContext (line 289) | function captureApplicationContext(context, n, f){
function debugCaptureApplicationContext (line 293) | function debugCaptureApplicationContext(context, n, f){
function captureStackTraceFallback (line 297) | function captureStackTraceFallback(x){
function entry (line 356) | function entry(o) {
function sortedKeys (line 363) | function sortedKeys(o) {
function show (line 412) | function show(x) {
function noop (line 500) | function noop(){}
function moop (line 501) | function moop(){ return this }
function call (line 502) | function call(f, x){ return f(x) }
function setImmediateFallback (line 504) | function setImmediateFallback(f, x){
function raise (line 508) | function raise(x){
function showArg$1 (line 514) | function showArg$1(x){
function error (line 518) | function error(message){
function typeError (line 522) | function typeError(message){
function invalidArgument (line 526) | function invalidArgument(it, at, expected, actual){
function invalidArgumentOf (line 533) | function invalidArgumentOf(expected){
function invalidArity (line 539) | function invalidArity(f, args){
function invalidNamespace (line 553) | function invalidNamespace(m, x){
function invalidVersion (line 562) | function invalidVersion(m, x){
function invalidFuture (line 572) | function invalidFuture(desc, m, s){
function invalidFutureArgument (line 584) | function invalidFutureArgument(it, at, m, s){
function ensureError (line 588) | function ensureError(value, fn){
function assignUnenumerable (line 601) | function assignUnenumerable(o, prop, value){
function wrapException (line 605) | function wrapException(caught, callingFuture){
function withExtraContext (line 615) | function withExtraContext(e, context){
function contextToStackTrace (line 621) | function contextToStackTrace(context){
function isFunction (line 630) | function isFunction(f){
function isThenable (line 634) | function isThenable(m){
function isBoolean (line 638) | function isBoolean(f){
function isNumber (line 642) | function isNumber(f){
function isUnsigned (line 646) | function isUnsigned(n){
function isObject (line 650) | function isObject(o){
function isIterator (line 654) | function isIterator(i){
function isArray (line 658) | function isArray(x){
function hasMethod (line 662) | function hasMethod(method, x){
function isFunctor (line 666) | function isFunctor(x){
function isAlt (line 670) | function isAlt(x){
function isApply (line 674) | function isApply(x){
function isBifunctor (line 678) | function isBifunctor(x){
function isChain (line 682) | function isChain(x){
function Next (line 686) | function Next(x){
function Done (line 690) | function Done(x){
function isIteration (line 694) | function isIteration(x){
function alwaysTrue (line 700) | function alwaysTrue(){
function getArgs (line 704) | function getArgs(it){
function showArg (line 712) | function showArg(arg){
function application (line 721) | function application(n, f, type, args, prev){
function application1 (line 728) | function application1(f, type, args){
function Future (line 732) | function Future(computation){
function isFuture (line 737) | function isFuture(x){
function createInterpreter (line 812) | function createInterpreter(arity, name, interpret){
function isNever (line 877) | function isNever(x){
function crash (line 886) | function crash(x){
function reject (line 899) | function reject(x){
function resolve (line 912) | function resolve(x){
function chainRec (line 918) | function chainRec(step, init){
function nextHot (line 942) | function nextHot(){
function nextCold (line 949) | function nextCold(){
function settle (line 960) | function settle(m){
function rejected (line 977) | function rejected(x){
function resolved (line 984) | function resolved(x){
function early (line 995) | function early(m, terminator){
function Sequence$cancel (line 1006) | function Sequence$cancel(){
function exception (line 1013) | function exception(e){
function warmupActions (line 1027) | function warmupActions(){
function drain (line 1040) | function drain(){
function BaseTransformation$rejected (line 1077) | function BaseTransformation$rejected(x){
function BaseTransformation$resolved (line 1082) | function BaseTransformation$resolved(x){
function BaseTransformation$toJSON (line 1087) | function BaseTransformation$toJSON(){
function wrapHandler (line 1102) | function wrapHandler(handler){
function createTransformation (line 1120) | function createTransformation(arity, name, prototype){
function alwaysNever$1 (line 1188) | function alwaysNever$1(_){
function after (line 1192) | function after(time){
function alt (line 1202) | function alt(left){
function and (line 1222) | function and(left){
function ap (line 1232) | function ap(mx){
function invalidPromise (line 1248) | function invalidPromise(p, f, a){
function encaseP (line 1282) | function encaseP(f){
function attemptP (line 1290) | function attemptP(_){
function encase (line 1301) | function encase(f){
function attempt (line 1309) | function attempt(_){
function bimap (line 1315) | function bimap(f){
function bichain (line 1333) | function bichain(f){
function Eager (line 1344) | function Eager(future){
function earlyCrash (line 1385) | function earlyCrash(early, x){
function earlyReject (line 1389) | function earlyReject(early, x){
function earlyResolve (line 1393) | function earlyResolve(early, x){
function createParallelTransformation (line 1397) | function createParallelTransformation(name, rec, rej, res, prototype){
function both (line 1427) | function both(left){
function Queued (line 1441) | function Queued(rec, rej, res){
function cache (line 1552) | function cache(m){
function chainRej (line 1560) | function chainRej(f){
function chain (line 1570) | function chain(f){
function done (line 1580) | function done(callback){
function extractLeft (line 1591) | function extractLeft(m){
function extractRight (line 1596) | function extractRight(m){
function coalesce (line 1610) | function coalesce(f){
function forkCatch (line 1621) | function forkCatch(f){
function fork (line 1635) | function fork(f){
function invalidIteration (line 1652) | function invalidIteration(o){
function invalidState (line 1659) | function invalidState(x){
function crash (line 1670) | function crash(e){
function resolved (line 1686) | function resolved(x){
function drain (line 1692) | function drain(){
function go (line 1718) | function go(generator){
function invalidDisposal (line 1722) | function invalidDisposal(m, f, x){
function invalidConsumption (line 1729) | function invalidConsumption(m, f, x){
function Hook$done (line 1741) | function Hook$done(){
function Hook$rec (line 1745) | function Hook$rec(x){
function Hook$dispose (line 1749) | function Hook$dispose(){
function Hook$cancelConsumption (line 1763) | function Hook$cancelConsumption(){
function Hook$cancelDisposal (line 1769) | function Hook$cancelDisposal(){
function Hook$disposalRejected (line 1773) | function Hook$disposalRejected(x){
function Hook$consumptionException (line 1777) | function Hook$consumptionException(x){
function Hook$consumptionRejected (line 1783) | function Hook$consumptionRejected(x){
function Hook$consumptionResolved (line 1789) | function Hook$consumptionResolved(x){
function Hook$consume (line 1795) | function Hook$consume(x){
function hook (line 1824) | function hook(acquire){
function lastly (line 1844) | function lastly(cleanup){
function mapRej (line 1858) | function mapRej(f){
function map (line 1868) | function map(f){
function Node$done (line 1879) | function Node$done(err, val){
function node (line 1903) | function node(f){
function pap (line 1918) | function pap(mx){
function isFutureArray (line 1926) | function isFutureArray(xs){
function Parallel$cancel (line 1945) | function Parallel$cancel(){
function Parallel$run (line 1953) | function Parallel$run(idx){
function Parallel$drain (line 1974) | function Parallel$drain(){
function parallel$1 (line 1988) | function parallel$1(max){
function race (line 1999) | function race(left){
function ConcurrentFuture (line 2007) | function ConcurrentFuture (sequential){
function Par (line 2013) | function Par (sequential){
function isParallel (line 2077) | function isParallel(x){
function promise (line 2081) | function promise(m){
function alwaysNever (line 2098) | function alwaysNever(_){
function rejectAfter (line 2102) | function rejectAfter(time){
function seq (line 2112) | function seq(par){
function swap (line 2126) | function swap(m){
function value (line 2131) | function value(res){
FILE: dist/module.js
function createCommonjsModule (line 7) | function createCommonjsModule(fn) {
function type (line 136) | function type(x) {
function List (line 203) | function List(head, tail){
function isNil (line 215) | function isNil(list){
function cons (line 221) | function cons(head, tail){
function reverse (line 227) | function reverse(xs){
function cat (line 238) | function cat(xs, ys){
function toArray (line 249) | function toArray(xs){
function debugMode (line 262) | function debugMode(debug){
function debugHandleNone (line 266) | function debugHandleNone(x){
function debugHandleAll (line 270) | function debugHandleAll(x, fn, a, b, c){
function debug (line 274) | function debug(x, fn, a, b, c){
function captureContext (line 278) | function captureContext(previous, tag, fn){
function debugCaptureContext (line 282) | function debugCaptureContext(previous, tag, fn){
function captureApplicationContext (line 288) | function captureApplicationContext(context, n, f){
function debugCaptureApplicationContext (line 292) | function debugCaptureApplicationContext(context, n, f){
function captureStackTraceFallback (line 296) | function captureStackTraceFallback(x){
function entry (line 355) | function entry(o) {
function sortedKeys (line 362) | function sortedKeys(o) {
function show (line 411) | function show(x) {
function noop (line 499) | function noop(){}
function moop (line 500) | function moop(){ return this }
function call (line 501) | function call(f, x){ return f(x) }
function setImmediateFallback (line 503) | function setImmediateFallback(f, x){
function raise (line 507) | function raise(x){
function showArg$1 (line 513) | function showArg$1(x){
function error (line 517) | function error(message){
function typeError (line 521) | function typeError(message){
function invalidArgument (line 525) | function invalidArgument(it, at, expected, actual){
function invalidArgumentOf (line 532) | function invalidArgumentOf(expected){
function invalidArity (line 538) | function invalidArity(f, args){
function invalidNamespace (line 552) | function invalidNamespace(m, x){
function invalidVersion (line 561) | function invalidVersion(m, x){
function invalidFuture (line 571) | function invalidFuture(desc, m, s){
function invalidFutureArgument (line 583) | function invalidFutureArgument(it, at, m, s){
function ensureError (line 587) | function ensureError(value, fn){
function assignUnenumerable (line 600) | function assignUnenumerable(o, prop, value){
function wrapException (line 604) | function wrapException(caught, callingFuture){
function withExtraContext (line 614) | function withExtraContext(e, context){
function contextToStackTrace (line 620) | function contextToStackTrace(context){
function isFunction (line 629) | function isFunction(f){
function isThenable (line 633) | function isThenable(m){
function isBoolean (line 637) | function isBoolean(f){
function isNumber (line 641) | function isNumber(f){
function isUnsigned (line 645) | function isUnsigned(n){
function isObject (line 649) | function isObject(o){
function isIterator (line 653) | function isIterator(i){
function isArray (line 657) | function isArray(x){
function hasMethod (line 661) | function hasMethod(method, x){
function isFunctor (line 665) | function isFunctor(x){
function isAlt (line 669) | function isAlt(x){
function isApply (line 673) | function isApply(x){
function isBifunctor (line 677) | function isBifunctor(x){
function isChain (line 681) | function isChain(x){
function Next (line 685) | function Next(x){
function Done (line 689) | function Done(x){
function isIteration (line 693) | function isIteration(x){
function alwaysTrue (line 699) | function alwaysTrue(){
function getArgs (line 703) | function getArgs(it){
function showArg (line 711) | function showArg(arg){
function application (line 720) | function application(n, f, type, args, prev){
function application1 (line 727) | function application1(f, type, args){
function Future (line 731) | function Future(computation){
function isFuture (line 736) | function isFuture(x){
function createInterpreter (line 811) | function createInterpreter(arity, name, interpret){
function isNever (line 876) | function isNever(x){
function crash (line 885) | function crash(x){
function reject (line 898) | function reject(x){
function resolve (line 911) | function resolve(x){
function chainRec (line 917) | function chainRec(step, init){
function nextHot (line 941) | function nextHot(){
function nextCold (line 948) | function nextCold(){
function settle (line 959) | function settle(m){
function rejected (line 976) | function rejected(x){
function resolved (line 983) | function resolved(x){
function early (line 994) | function early(m, terminator){
function Sequence$cancel (line 1005) | function Sequence$cancel(){
function exception (line 1012) | function exception(e){
function warmupActions (line 1026) | function warmupActions(){
function drain (line 1039) | function drain(){
function BaseTransformation$rejected (line 1076) | function BaseTransformation$rejected(x){
function BaseTransformation$resolved (line 1081) | function BaseTransformation$resolved(x){
function BaseTransformation$toJSON (line 1086) | function BaseTransformation$toJSON(){
function wrapHandler (line 1101) | function wrapHandler(handler){
function createTransformation (line 1119) | function createTransformation(arity, name, prototype){
function alwaysNever$1 (line 1187) | function alwaysNever$1(_){
function after (line 1191) | function after(time){
function alt (line 1201) | function alt(left){
function and (line 1221) | function and(left){
function ap (line 1231) | function ap(mx){
function invalidPromise (line 1247) | function invalidPromise(p, f, a){
function encaseP (line 1281) | function encaseP(f){
function attemptP (line 1289) | function attemptP(_){
function encase (line 1300) | function encase(f){
function attempt (line 1308) | function attempt(_){
function bimap (line 1314) | function bimap(f){
function bichain (line 1332) | function bichain(f){
function Eager (line 1343) | function Eager(future){
function earlyCrash (line 1384) | function earlyCrash(early, x){
function earlyReject (line 1388) | function earlyReject(early, x){
function earlyResolve (line 1392) | function earlyResolve(early, x){
function createParallelTransformation (line 1396) | function createParallelTransformation(name, rec, rej, res, prototype){
function both (line 1426) | function both(left){
function Queued (line 1440) | function Queued(rec, rej, res){
function cache (line 1551) | function cache(m){
function chainRej (line 1559) | function chainRej(f){
function chain (line 1569) | function chain(f){
function done (line 1579) | function done(callback){
function extractLeft (line 1590) | function extractLeft(m){
function extractRight (line 1595) | function extractRight(m){
function coalesce (line 1609) | function coalesce(f){
function forkCatch (line 1620) | function forkCatch(f){
function fork (line 1634) | function fork(f){
function invalidIteration (line 1651) | function invalidIteration(o){
function invalidState (line 1658) | function invalidState(x){
function crash (line 1669) | function crash(e){
function resolved (line 1685) | function resolved(x){
function drain (line 1691) | function drain(){
function go (line 1717) | function go(generator){
function invalidDisposal (line 1721) | function invalidDisposal(m, f, x){
function invalidConsumption (line 1728) | function invalidConsumption(m, f, x){
function Hook$done (line 1740) | function Hook$done(){
function Hook$rec (line 1744) | function Hook$rec(x){
function Hook$dispose (line 1748) | function Hook$dispose(){
function Hook$cancelConsumption (line 1762) | function Hook$cancelConsumption(){
function Hook$cancelDisposal (line 1768) | function Hook$cancelDisposal(){
function Hook$disposalRejected (line 1772) | function Hook$disposalRejected(x){
function Hook$consumptionException (line 1776) | function Hook$consumptionException(x){
function Hook$consumptionRejected (line 1782) | function Hook$consumptionRejected(x){
function Hook$consumptionResolved (line 1788) | function Hook$consumptionResolved(x){
function Hook$consume (line 1794) | function Hook$consume(x){
function hook (line 1823) | function hook(acquire){
function lastly (line 1843) | function lastly(cleanup){
function mapRej (line 1857) | function mapRej(f){
function map (line 1867) | function map(f){
function Node$done (line 1878) | function Node$done(err, val){
function node (line 1902) | function node(f){
function pap (line 1917) | function pap(mx){
function isFutureArray (line 1925) | function isFutureArray(xs){
function Parallel$cancel (line 1944) | function Parallel$cancel(){
function Parallel$run (line 1952) | function Parallel$run(idx){
function Parallel$drain (line 1973) | function Parallel$drain(){
function parallel$1 (line 1987) | function parallel$1(max){
function race (line 1998) | function race(left){
function ConcurrentFuture (line 2006) | function ConcurrentFuture (sequential){
function Par (line 2012) | function Par (sequential){
function isParallel (line 2076) | function isParallel(x){
function promise (line 2080) | function promise(m){
function alwaysNever (line 2097) | function alwaysNever(_){
function rejectAfter (line 2101) | function rejectAfter(time){
function seq (line 2111) | function seq(par){
function swap (line 2125) | function swap(m){
function value (line 2130) | function value(res){
FILE: index.d.ts
type RecoverFunction (line 4) | interface RecoverFunction {
type RejectFunction (line 8) | interface RejectFunction<L> {
type ResolveFunction (line 12) | interface ResolveFunction<R> {
type Cancel (line 16) | interface Cancel {
type Nodeback (line 20) | interface Nodeback<E, R> {
type Functor (line 26) | interface Functor<A> {
type Mapped (line 31) | type Mapped<F extends Functor<unknown>, B> = ReturnType<(F & { [$T]: B }...
type ConcurrentFutureInstance (line 33) | interface ConcurrentFutureInstance<L, R> extends Functor<R> {
type FutureInstance (line 40) | interface FutureInstance<L, R> extends Functor<R> {
type FutureTypeRep (line 191) | interface FutureTypeRep {
type ConcurrentFutureTypeRep (line 209) | interface ConcurrentFutureTypeRep {
FILE: src/after.js
function alwaysNever (line 19) | function alwaysNever(_){
function after (line 23) | function after(time){
FILE: src/alt.js
function alt (line 14) | function alt(left){
FILE: src/and.js
function and (line 7) | function and(left){
FILE: src/ap.js
function ap (line 8) | function ap(mx){
FILE: src/attempt-p.js
function attemptP (line 3) | function attemptP(_){
FILE: src/attempt.js
function attempt (line 3) | function attempt(_){
FILE: src/bichain.js
function bichain (line 9) | function bichain(f){
FILE: src/bimap.js
function bimap (line 8) | function bimap(f){
FILE: src/both.js
function both (line 18) | function both(left){
FILE: src/cache.js
function Queued (line 10) | function Queued(rec, rej, res){
function cache (line 121) | function cache(m){
FILE: src/chain-rej.js
function chainRej (line 8) | function chainRej(f){
FILE: src/chain.js
function chain (line 8) | function chain(f){
FILE: src/coalesce.js
function coalesce (line 13) | function coalesce(f){
FILE: src/done.js
function done (line 4) | function done(callback){
FILE: src/encase-p.js
function invalidPromise (line 6) | function invalidPromise(p, f, a){
function encaseP (line 40) | function encaseP(f){
FILE: src/encase.js
function encase (line 11) | function encase(f){
FILE: src/extract-left.js
function extractLeft (line 3) | function extractLeft(m){
FILE: src/extract-right.js
function extractRight (line 3) | function extractRight(m){
FILE: src/fork-catch.js
function forkCatch (line 3) | function forkCatch(f){
FILE: src/fork.js
function fork (line 4) | function fork(f){
FILE: src/future.js
function alwaysTrue (line 21) | function alwaysTrue(){
function getArgs (line 25) | function getArgs(it){
function showArg (line 33) | function showArg(arg){
function application (line 42) | function application(n, f, type, args, prev){
function application1 (line 49) | function application1(f, type, args){
function Future (line 53) | function Future(computation){
function isFuture (line 58) | function isFuture(x){
function createInterpreter (line 133) | function createInterpreter(arity, name, interpret){
function isNever (line 198) | function isNever(x){
function crash (line 207) | function crash(x){
function reject (line 220) | function reject(x){
function resolve (line 233) | function resolve(x){
function chainRec (line 239) | function chainRec(step, init){
function nextHot (line 262) | function nextHot(){
function nextCold (line 269) | function nextCold(){
function settle (line 280) | function settle(m){
function rejected (line 297) | function rejected(x){
function resolved (line 304) | function resolved(x){
function early (line 315) | function early(m, terminator){
function Sequence$cancel (line 326) | function Sequence$cancel(){
function exception (line 333) | function exception(e){
function warmupActions (line 347) | function warmupActions(){
function drain (line 360) | function drain(){
function BaseTransformation$rejected (line 396) | function BaseTransformation$rejected(x){
function BaseTransformation$resolved (line 401) | function BaseTransformation$resolved(x){
function BaseTransformation$toJSON (line 406) | function BaseTransformation$toJSON(){
function wrapHandler (line 421) | function wrapHandler(handler){
function createTransformation (line 439) | function createTransformation(arity, name, prototype){
FILE: src/go.js
function invalidIteration (line 10) | function invalidIteration(o){
function invalidState (line 17) | function invalidState(x){
function crash (line 27) | function crash(e){
function resolved (line 43) | function resolved(x){
function drain (line 49) | function drain(){
function go (line 72) | function go(generator){
FILE: src/hook.js
function invalidDisposal (line 5) | function invalidDisposal(m, f, x){
function invalidConsumption (line 12) | function invalidConsumption(m, f, x){
function Hook$done (line 23) | function Hook$done(){
function Hook$rec (line 27) | function Hook$rec(x){
function Hook$dispose (line 31) | function Hook$dispose(){
function Hook$cancelConsumption (line 45) | function Hook$cancelConsumption(){
function Hook$cancelDisposal (line 51) | function Hook$cancelDisposal(){
function Hook$disposalRejected (line 55) | function Hook$disposalRejected(x){
function Hook$consumptionException (line 59) | function Hook$consumptionException(x){
function Hook$consumptionRejected (line 65) | function Hook$consumptionRejected(x){
function Hook$consumptionResolved (line 71) | function Hook$consumptionResolved(x){
function Hook$consume (line 77) | function Hook$consume(x){
function hook (line 105) | function hook(acquire){
FILE: src/internal/debug.js
function debugMode (line 10) | function debugMode(debug){
function debugHandleNone (line 14) | function debugHandleNone(x){
function debugHandleAll (line 18) | function debugHandleAll(x, fn, a, b, c){
function debug (line 22) | function debug(x, fn, a, b, c){
function captureContext (line 26) | function captureContext(previous, tag, fn){
function debugCaptureContext (line 30) | function debugCaptureContext(previous, tag, fn){
function captureApplicationContext (line 36) | function captureApplicationContext(context, n, f){
function debugCaptureApplicationContext (line 40) | function debugCaptureApplicationContext(context, n, f){
function captureStackTraceFallback (line 44) | function captureStackTraceFallback(x){
FILE: src/internal/error.js
function showArg (line 7) | function showArg(x){
function error (line 11) | function error(message){
function typeError (line 15) | function typeError(message){
function invalidArgument (line 19) | function invalidArgument(it, at, expected, actual){
function invalidArgumentOf (line 26) | function invalidArgumentOf(expected){
function invalidContext (line 32) | function invalidContext(it, actual){
function invalidArity (line 39) | function invalidArity(f, args){
function invalidNamespace (line 53) | function invalidNamespace(m, x){
function invalidVersion (line 62) | function invalidVersion(m, x){
function invalidFuture (line 72) | function invalidFuture(desc, m, s){
function invalidFutureArgument (line 84) | function invalidFutureArgument(it, at, m, s){
function ensureError (line 88) | function ensureError(value, fn){
function assignUnenumerable (line 101) | function assignUnenumerable(o, prop, value){
function wrapException (line 105) | function wrapException(caught, callingFuture){
function withExtraContext (line 115) | function withExtraContext(e, context){
function contextToStackTrace (line 121) | function contextToStackTrace(context){
FILE: src/internal/iteration.js
function Next (line 3) | function Next(x){
function Done (line 7) | function Done(x){
function isIteration (line 11) | function isIteration(x){
FILE: src/internal/list.js
function List (line 1) | function List(head, tail){
function isNil (line 13) | function isNil(list){
function cons (line 19) | function cons(head, tail){
function reverse (line 25) | function reverse(xs){
function cat (line 36) | function cat(xs, ys){
function toArray (line 47) | function toArray(xs){
FILE: src/internal/parallel.js
function Eager (line 4) | function Eager(future){
function earlyCrash (line 45) | function earlyCrash(early, x){
function earlyReject (line 49) | function earlyReject(early, x){
function earlyResolve (line 53) | function earlyResolve(early, x){
function createParallelTransformation (line 57) | function createParallelTransformation(name, rec, rej, res, prototype){
FILE: src/internal/predicates.js
function isFunction (line 3) | function isFunction(f){
function isThenable (line 7) | function isThenable(m){
function isBoolean (line 11) | function isBoolean(f){
function isNumber (line 15) | function isNumber(f){
function isUnsigned (line 19) | function isUnsigned(n){
function isObject (line 23) | function isObject(o){
function isIterator (line 27) | function isIterator(i){
function isArray (line 31) | function isArray(x){
function hasMethod (line 35) | function hasMethod(method, x){
function isFunctor (line 39) | function isFunctor(x){
function isAlt (line 43) | function isAlt(x){
function isApply (line 47) | function isApply(x){
function isBifunctor (line 51) | function isBifunctor(x){
function isChain (line 55) | function isChain(x){
FILE: src/internal/utils.js
function noop (line 6) | function noop(){}
function moop (line 7) | function moop(){ return this }
function call (line 8) | function call(f, x){ return f(x) }
function setImmediateFallback (line 10) | function setImmediateFallback(f, x){
function raise (line 14) | function raise(x){
FILE: src/lastly.js
function lastly (line 20) | function lastly(cleanup){
FILE: src/map-rej.js
function mapRej (line 10) | function mapRej(f){
FILE: src/map.js
function map (line 8) | function map(f){
FILE: src/node.js
function Node$done (line 6) | function Node$done(err, val){
function node (line 30) | function node(f){
FILE: src/pap.js
function pap (line 19) | function pap(mx){
FILE: src/par.js
function ConcurrentFuture (line 12) | function ConcurrentFuture(sequential){
function Par (line 18) | function Par(sequential){
function isParallel (line 82) | function isParallel(x){
FILE: src/parallel.js
function isFutureArray (line 13) | function isFutureArray(xs){
function Parallel$cancel (line 31) | function Parallel$cancel(){
function Parallel$run (line 39) | function Parallel$run(idx){
function Parallel$drain (line 60) | function Parallel$drain(){
function parallel (line 73) | function parallel(max){
FILE: src/promise.js
function promise (line 3) | function promise(m){
FILE: src/race.js
function race (line 12) | function race(left){
FILE: src/reject-after.js
function alwaysNever (line 20) | function alwaysNever(_){
function rejectAfter (line 24) | function rejectAfter(time){
FILE: src/seq.js
function seq (line 7) | function seq(par){
FILE: src/swap.js
function swap (line 12) | function swap(m){
FILE: src/value.js
function value (line 5) | function value(res){
FILE: test/arbitraries.js
function AsyncResolvedFutureArb (line 21) | function AsyncResolvedFutureArb (arb){
function AsyncRejectedFutureArb (line 25) | function AsyncRejectedFutureArb (arb){
function ResolvedFutureArb (line 29) | function ResolvedFutureArb (arb){
function RejectedFutureArb (line 33) | function RejectedFutureArb (arb){
function FutureArb (line 37) | function FutureArb (larb, rarb){
FILE: test/assertions.js
function makeEquivalence (line 20) | function makeEquivalence (equals){
FILE: test/integration/main.js
function through (line 19) | function through (x, fs){
FILE: test/prop/0.algebra.js
function eq (line 32) | function eq (x){
FILE: test/prop/0.fantasy-land.js
function testLaw (line 34) | function testLaw (laws, typeclass, name){
FILE: test/prop/1.fantasy-libs.js
function bang (line 8) | function bang (x){
function compose (line 12) | function compose (f, g){
function square (line 18) | function square (x){
FILE: test/prop/2.arbitrary.js
function eq (line 32) | function eq (a){
FILE: test/unit/0.error.js
function args (line 16) | function args (){
FILE: test/unit/0.predicates.js
method then (line 13) | then (a){ return a }
method then (line 14) | then (a, b){ return b }
function O (line 39) | function O (){}
method next (line 47) | next (){}
method next (line 47) | next (x){ return x }
FILE: test/unit/2.fork-catch.js
function assertCrash (line 9) | function assertCrash (x){
function assertRejection (line 17) | function assertRejection (x){
function assertResolution (line 25) | function assertResolution (x){
FILE: test/unit/2.fork.js
function assertRejection (line 13) | function assertRejection (x){
function assertResolution (line 21) | function assertResolution (x){
FILE: test/util/props.js
function _of (line 33) | function _of (rarb){
function property (line 37) | function property (name){
function f (line 44) | function f (x){
function g (line 48) | function g (x){
function testFunction (line 131) | function testFunction (name, func, args, assert){
FILE: test/util/util.js
function test (line 20) | function test (name, impl){
function assertStackTrace (line 140) | function assertStackTrace (name, x){
Condensed preview — 139 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (415K chars).
[
{
"path": ".editorconfig",
"chars": 147,
"preview": "root = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ni"
},
{
"path": ".eslintignore",
"chars": 23,
"preview": "/test/build/require.js\n"
},
{
"path": ".eslintrc.json",
"chars": 1582,
"preview": "{\n \"root\": true,\n \"extends\": [\"warp\"],\n \"parserOptions\": {\n \"ecmaVersion\": 2015,\n \"sourceType\": \"module\"\n },\n "
},
{
"path": ".github/FUNDING.yml",
"chars": 15,
"preview": "github: [Avaq]\n"
},
{
"path": ".github/dependabot.yml",
"chars": 147,
"preview": "version: 2\nupdates:\n- package-ecosystem: npm\n directory: \"/\"\n schedule:\n interval: daily\n open-pull-requests-limit"
},
{
"path": ".github/workflows/test.yml",
"chars": 528,
"preview": "name: Test\n\non:\n pull_request:\n push:\n branches:\n - master\n - 11.x\n\njobs:\n test:\n runs-on: ubuntu-lat"
},
{
"path": ".gitignore",
"chars": 66,
"preview": "/bench/node_modules/\n/coverage/\n/node_modules/\n/perf/\n\n/index.cjs\n"
},
{
"path": ".npmrc",
"chars": 19,
"preview": "package-lock=false\n"
},
{
"path": "CHANGELOG.md",
"chars": 99,
"preview": "# Change Log\n\nPlease refer to the [release notes](https://github.com/fluture-js/Fluture/releases).\n"
},
{
"path": "CONTRIBUTING.md",
"chars": 200,
"preview": "# Contribution guide\n\n## Making a contribution\n\n* Fork and clone the project\n* Commit changes to a branch named after th"
},
{
"path": "LICENSE",
"chars": 1081,
"preview": "The MIT License (MIT)\nCopyright (c) 2020 Aldwin Vlasblom\n\nPermission is hereby granted, free of charge, to any person ob"
},
{
"path": "README.md",
"chars": 55462,
"preview": "# [](#butterfly)\n\n[![Build Status][]](https://github.com/fluture-js/Fluture/actions?query=branch%3Am"
},
{
"path": "bench/.eslintrc.json",
"chars": 96,
"preview": "{\n \"root\": true,\n \"extends\": [\"warp/node\", \"warp/es6\"],\n \"rules\": {\n \"max-len\": [0]\n }\n}\n"
},
{
"path": "bench/.npmrc",
"chars": 30,
"preview": "package-lock=false\nsave=false\n"
},
{
"path": "bench/README.md",
"chars": 371,
"preview": "# Benchmarks\n\n## Running\n\n* Install node modules required for the benchmark you wish to run\n* Use `npm run bench -- --he"
},
{
"path": "bench/fluture.js",
"chars": 4553,
"preview": "/* global setImmediate */\n\nimport bench from 'sanctuary-benchmark';\nimport Old from 'fluture';\nimport * as New from '../"
},
{
"path": "bench/folktale.js",
"chars": 1564,
"preview": "import bench from 'sanctuary-benchmark';\nimport * as Future from '../index.js';\nimport folktale from 'folktale/concurren"
},
{
"path": "bench/package.json",
"chars": 298,
"preview": "{\n \"name\": \"fluture-benchmarks\",\n \"type\": \"module\",\n \"version\": \"1.0.0\",\n \"description\": \"A package.json for the pur"
},
{
"path": "bench/promise.js",
"chars": 1530,
"preview": "import bench from 'sanctuary-benchmark';\nimport * as Future from '../index.js';\n\nconst plus1 = x => x + 1;\nconst repeat "
},
{
"path": "dist/bundle.js",
"chars": 65520,
"preview": "/**\n * Fluture bundled; version 14.0.0\n */\n\nvar Fluture = (function () {\n\t'use strict';\n\n\tfunction createCommonjsModule("
},
{
"path": "dist/module.js",
"chars": 63214,
"preview": "/**\n * Fluture bundled; version 14.0.0\n */\n\n/// <reference types=\"https://cdn.jsdelivr.net/gh/fluture-js/Fluture@14.0.0/"
},
{
"path": "index.cjs.js",
"chars": 94,
"preview": "import * as Fluture from './index.js';\nexport default Object.assign(Fluture.Future, Fluture);\n"
},
{
"path": "index.d.ts",
"chars": 12413,
"preview": "/// <reference lib=\"es2015.generator\" />\n/// <reference lib=\"es2015.iterable\" />\n\nexport interface RecoverFunction {\n ("
},
{
"path": "index.js",
"chars": 1552,
"preview": "export {\n Future as default,\n Future,\n isFuture,\n isNever,\n never,\n reject,\n resolve,\n} from './src/future.js';\n\n"
},
{
"path": "package.json",
"chars": 3109,
"preview": "{\n \"name\": \"fluture\",\n \"version\": \"14.0.0\",\n \"description\": \"FantasyLand compliant (monadic) alternative to Promises\""
},
{
"path": "rollup.config.dist.js",
"chars": 1421,
"preview": "/* global process Set */\n\nimport {readFileSync} from 'fs';\nimport node from '@rollup/plugin-node-resolve';\nimport common"
},
{
"path": "rollup.config.js",
"chars": 313,
"preview": "var dependencies = {\n 'sanctuary-show': 'sanctuaryShow',\n 'sanctuary-type-identifiers': 'sanctuaryTypeIdentifiers',\n};"
},
{
"path": "scripts/bench.js",
"chars": 214,
"preview": "const suite = process.argv[2];\nconst options = process.argv[3] ? JSON.parse(process.argv[3]) : {};\n\nimport(`../bench/${s"
},
{
"path": "scripts/distribute",
"chars": 373,
"preview": "#!/usr/bin/env bash\nset -eufo pipefail\n\necho \"Publishing as $(npm whoami).\"\n\nif ! npm outdated --long; then\n read -rp \""
},
{
"path": "scripts/test-esm",
"chars": 375,
"preview": "#!/usr/bin/env bash\nset -eufo pipefail\n\nversion=$(node --print 'process.versions.node.split(\".\")[0]')\n\nif [[ \"$version\" "
},
{
"path": "scripts/test-mem",
"chars": 2377,
"preview": "#!/usr/bin/env node\n\n/* global process setImmediate */\n\nimport {Future, fork, race, chain, resolve as sync} from '../ind"
},
{
"path": "src/after.js",
"chars": 727,
"preview": "import {\n any,\n application,\n application1,\n createInterpreter,\n never,\n positiveInteger,\n} from './future.js';\n\ne"
},
{
"path": "src/alt.js",
"chars": 817,
"preview": "import {FL} from './internal/const.js';\nimport {invalidArgumentOf} from './internal/error.js';\nimport {isAlt} from './in"
},
{
"path": "src/and.js",
"chars": 480,
"preview": "import {createTransformation, application1, application, future} from './future.js';\n\nexport var AndTransformation = cre"
},
{
"path": "src/ap.js",
"chars": 762,
"preview": "import {FL} from './internal/const.js';\nimport {invalidArgumentOf} from './internal/error.js';\nimport {isApply} from './"
},
{
"path": "src/attempt-p.js",
"chars": 123,
"preview": "import {encaseP} from './encase-p.js';\n\nexport function attemptP(_){\n return encaseP.apply(this, arguments)(undefined);"
},
{
"path": "src/attempt.js",
"chars": 118,
"preview": "import {encase} from './encase.js';\n\nexport function attempt(_){\n return encase.apply(this, arguments)(undefined);\n}\n"
},
{
"path": "src/bichain.js",
"chars": 754,
"preview": "import {createTransformation, future, application1, application, func} from './future.js';\nimport {call} from './interna"
},
{
"path": "src/bimap.js",
"chars": 769,
"preview": "import {FL} from './internal/const.js';\nimport {invalidArgumentOf} from './internal/error.js';\nimport {isBifunctor} from"
},
{
"path": "src/both.js",
"chars": 910,
"preview": "import {createParallelTransformation, earlyCrash, earlyReject} from './internal/parallel.js';\nimport {noop} from './inte"
},
{
"path": "src/cache.js",
"chars": 3231,
"preview": "import {noop} from './internal/utils.js';\nimport {createInterpreter, application1, future} from './future.js';\n\nexport v"
},
{
"path": "src/chain-rej.js",
"chars": 562,
"preview": "import {call} from './internal/utils.js';\nimport {createTransformation, application1, application, future, func} from '."
},
{
"path": "src/chain.js",
"chars": 629,
"preview": "import {FL} from './internal/const.js';\nimport {invalidArgumentOf} from './internal/error.js';\nimport {isChain} from './"
},
{
"path": "src/coalesce.js",
"chars": 842,
"preview": "import {call} from './internal/utils.js';\nimport {createTransformation, Resolve, application1, application, func, future"
},
{
"path": "src/done.js",
"chars": 391,
"preview": "import {application1, application, func, future} from './future.js';\nimport {raise} from './internal/utils.js';\n\nexport "
},
{
"path": "src/encase-p.js",
"chars": 1288,
"preview": "import {wrapException, typeError} from './internal/error.js';\nimport {isThenable} from './internal/predicates.js';\nimpor"
},
{
"path": "src/encase.js",
"chars": 557,
"preview": "import {noop} from './internal/utils.js';\nimport {createInterpreter, application1, application, func, any} from './futur"
},
{
"path": "src/extract-left.js",
"chars": 159,
"preview": "import {application1, future} from './future.js';\n\nexport function extractLeft(m){\n application1(extractLeft, future, a"
},
{
"path": "src/extract-right.js",
"chars": 162,
"preview": "import {application1, future} from './future.js';\n\nexport function extractRight(m){\n application1(extractRight, future,"
},
{
"path": "src/fork-catch.js",
"chars": 534,
"preview": "import {application, application1, func, future} from './future.js';\n\nexport function forkCatch(f){\n var context1 = app"
},
{
"path": "src/fork.js",
"chars": 427,
"preview": "import {raise} from './internal/utils.js';\nimport {application, application1, func, future} from './future.js';\n\nexport "
},
{
"path": "src/future.js",
"chars": 15411,
"preview": "/* eslint no-cond-assign:0, no-constant-condition:0 */\nimport type from 'sanctuary-type-identifiers';\n\nimport {FL, $$typ"
},
{
"path": "src/go.js",
"chars": 2089,
"preview": "/* eslint consistent-return: 0 */\n\nimport {typeError, invalidFuture, invalidArgument, wrapException} from './internal/er"
},
{
"path": "src/hook.js",
"chars": 2958,
"preview": "import {noop, show, raise} from './internal/utils.js';\nimport {invalidFuture, wrapException} from './internal/error.js';"
},
{
"path": "src/internal/const.js",
"chars": 472,
"preview": "export var FL = {\n alt: 'fantasy-land/alt',\n ap: 'fantasy-land/ap',\n bimap: 'fantasy-land/bimap',\n chain: 'fantasy-l"
},
{
"path": "src/internal/debug.js",
"chars": 1343,
"preview": "import {ordinal} from './const.js';\nimport {cons} from './list.js';\n\n/* c8 ignore next */\nvar captureStackTrace = Error."
},
{
"path": "src/internal/error.js",
"chars": 4031,
"preview": "import {show} from './utils.js';\nimport {ordinal, namespace, name, version} from './const.js';\nimport type from 'sanctua"
},
{
"path": "src/internal/iteration.js",
"chars": 254,
"preview": "import {isObject, isBoolean} from './predicates.js';\n\nexport function Next(x){\n return {done: false, value: x};\n}\n\nexpo"
},
{
"path": "src/internal/list.js",
"chars": 1048,
"preview": "export function List(head, tail){\n this.head = head;\n this.tail = tail;\n}\n\nList.prototype.toJSON = function(){\n retur"
},
{
"path": "src/internal/parallel.js",
"chars": 1944,
"preview": "import {noop} from './utils.js';\nimport {createTransformation, Future, crash, reject, resolve} from '../future.js';\n\nfun"
},
{
"path": "src/internal/predicates.js",
"chars": 1108,
"preview": "import {FL} from './const.js';\n\nexport function isFunction(f){\n return typeof f === 'function';\n}\n\nexport function isTh"
},
{
"path": "src/internal/timing.js",
"chars": 86,
"preview": "export var Undetermined = 0;\nexport var Synchronous = 1;\nexport var Asynchronous = 2;\n"
},
{
"path": "src/internal/utils.js",
"chars": 462,
"preview": "export {default as show} from 'sanctuary-show';\n\n/* c8 ignore next */\nvar setImmediate = typeof setImmediate === 'undefi"
},
{
"path": "src/lastly.js",
"chars": 817,
"preview": "import {AndTransformation} from './and.js';\nimport {\n application,\n application1,\n createTransformation,\n future,\n "
},
{
"path": "src/map-rej.js",
"chars": 587,
"preview": "import {call} from './internal/utils.js';\nimport {createTransformation, Reject, application1, application, future, func}"
},
{
"path": "src/map.js",
"chars": 625,
"preview": "import {FL} from './internal/const.js';\nimport {invalidArgumentOf} from './internal/error.js';\nimport {isFunctor} from '"
},
{
"path": "src/node.js",
"chars": 804,
"preview": "import {wrapException} from './internal/error.js';\nimport {noop, call} from './internal/utils.js';\nimport {createInterpr"
},
{
"path": "src/pap.js",
"chars": 1003,
"preview": "import {createParallelTransformation, earlyCrash, earlyReject} from './internal/parallel.js';\nimport {noop} from './inte"
},
{
"path": "src/par.js",
"chars": 2455,
"preview": "import type from 'sanctuary-type-identifiers';\n\nimport {FL, namespace, version} from './internal/const.js';\nimport {inva"
},
{
"path": "src/parallel.js",
"chars": 2130,
"preview": "import {wrapException, invalidArgumentOf} from './internal/error.js';\nimport {isArray} from './internal/predicates.js';\n"
},
{
"path": "src/promise.js",
"chars": 225,
"preview": "import {application1, future} from './future.js';\n\nexport function promise(m){\n application1(promise, future, arguments"
},
{
"path": "src/race.js",
"chars": 558,
"preview": "import {\n createParallelTransformation,\n earlyCrash,\n earlyReject,\n earlyResolve,\n} from './internal/parallel.js';\ni"
},
{
"path": "src/reject-after.js",
"chars": 786,
"preview": "import {\n any,\n application,\n application1,\n createInterpreter,\n never,\n positiveInteger,\n} from './future.js';\n\ne"
},
{
"path": "src/seq.js",
"chars": 317,
"preview": "import {invalidArgumentOf} from './internal/error.js';\nimport {application1} from './future.js';\nimport {isParallel} fro"
},
{
"path": "src/swap.js",
"chars": 496,
"preview": "import {createTransformation, Reject, Resolve, application1, future} from './future.js';\n\nexport var SwapTransformation "
},
{
"path": "src/value.js",
"chars": 579,
"preview": "import {error} from './internal/error.js';\nimport {raise, show} from './internal/utils.js';\nimport {application1, applic"
},
{
"path": "test/arbitraries.js",
"chars": 1895,
"preview": "import jsv from 'jsverify';\nimport {Future, resolve, reject, Par, seq, extractLeft, extractRight} from '../index.js';\n\nc"
},
{
"path": "test/assertions.js",
"chars": 3396,
"preview": "import show from 'sanctuary-show';\nimport type from 'sanctuary-type-identifiers';\nimport {Future, isFuture} from '../ind"
},
{
"path": "test/build/main.js",
"chars": 731,
"preview": "import {noop, eq, test} from '../util/util.js';\nimport * as Fluture from '../../index.js';\nimport require from './requir"
},
{
"path": "test/build/require.js",
"chars": 85,
"preview": "import {createRequire} from 'module';\nexport default createRequire(import.meta.url);\n"
},
{
"path": "test/integration/main.js",
"chars": 4687,
"preview": "import {\n Future,\n after,\n ap,\n both,\n cache,\n chain,\n fork,\n map,\n parallel,\n race,\n rejectAfter,\n resolve,"
},
{
"path": "test/prop/0.algebra.js",
"chars": 4070,
"preview": "import show from 'sanctuary-show';\nimport {assertEqual, I, B, T, K} from '../util/util.js';\nimport {FutureArb, any as _x"
},
{
"path": "test/prop/0.fantasy-land.js",
"chars": 2674,
"preview": "import FL from 'fantasy-laws';\nimport Z from 'sanctuary-type-classes';\nimport show from 'sanctuary-show';\nimport {Future"
},
{
"path": "test/prop/1.fantasy-libs.js",
"chars": 1949,
"preview": "import * as R from 'ramda';\nimport Z from 'sanctuary-type-classes';\nimport {Future, ap, alt, map, bimap, chain, resolve,"
},
{
"path": "test/prop/2.arbitrary.js",
"chars": 3065,
"preview": "import {assertEqual, I, B, K} from '../util/util.js';\nimport {\n any,\n anyFuture,\n anyRejectedFuture,\n anyResolvedFut"
},
{
"path": "test/types/map.test-d.ts",
"chars": 1122,
"preview": "import {expectType} from 'tsd';\n\nimport * as fl from '../../index.js';\n\nconst resolved = fl.resolve (42);\nconst rejected"
},
{
"path": "test/unit/0.debug.js",
"chars": 2129,
"preview": "import {eq, error, assertStackTrace, K, I, test} from '../util/util.js';\nimport {\n debugMode,\n debug,\n captureContext"
},
{
"path": "test/unit/0.error.js",
"chars": 6149,
"preview": "import {eq, assertStackTrace, error as mockError, noop, test} from '../util/util.js';\nimport {mock} from '../util/future"
},
{
"path": "test/unit/0.iteration.js",
"chars": 518,
"preview": "import chai from 'chai';\nimport {test} from '../util/util.js';\nimport {Next, Done, isIteration} from '../../src/internal"
},
{
"path": "test/unit/0.list.js",
"chars": 654,
"preview": "import {eq, test} from '../util/util.js';\nimport {nil, cons, reverse, cat} from '../../src/internal/list.js';\n\ntest('rev"
},
{
"path": "test/unit/0.predicates.js",
"chars": 1895,
"preview": "import chai from 'chai';\nimport {test, eq, noop} from '../util/util.js';\nimport Future from '../../index.js';\nimport * a"
},
{
"path": "test/unit/0.utils.js",
"chars": 372,
"preview": "import chai from 'chai';\nimport {test} from '../util/util.js';\nimport {setImmediateFallback} from '../../src/internal/ut"
},
{
"path": "test/unit/1.future.js",
"chars": 2504,
"preview": "import Future from '../../index.js';\nimport {noop, eq, assertCrashed, assertResolved, error, assertValidFuture, test} fr"
},
{
"path": "test/unit/1.is-future.js",
"chars": 338,
"preview": "import {isFuture} from '../../index.js';\nimport {property, anyFuture, anyNonFuture} from '../util/props.js';\n\nproperty('"
},
{
"path": "test/unit/1.is-never.js",
"chars": 327,
"preview": "import {isNever, never} from '../../index.js';\nimport {any, property} from '../util/props.js';\nimport {eq, test} from '."
},
{
"path": "test/unit/1.never.js",
"chars": 430,
"preview": "import {never} from '../../index.js';\nimport {assertValidFuture, noop, eq, test} from '../util/util.js';\n\ntest('is a Fut"
},
{
"path": "test/unit/1.pipe.js",
"chars": 428,
"preview": "import {mock} from '../util/futures.js';\nimport {eq, throws, test} from '../util/util.js';\n\ntest('throws when not given "
},
{
"path": "test/unit/2.done.js",
"chars": 659,
"preview": "import {done} from '../../index.js';\nimport {testFunction, functionArg, resolvedFutureArg} from '../util/props.js';\nimpo"
},
{
"path": "test/unit/2.extract-left.js",
"chars": 385,
"preview": "import {extractLeft} from '../../index.js';\nimport {testFunction, futureArg} from '../util/props.js';\nimport {isArray, t"
},
{
"path": "test/unit/2.extract-right.js",
"chars": 391,
"preview": "import {extractRight} from '../../index.js';\nimport {testFunction, futureArg} from '../util/props.js';\nimport {isArray, "
},
{
"path": "test/unit/2.fork-catch.js",
"chars": 959,
"preview": "import {forkCatch} from '../../index.js';\nimport {testFunction, functionArg, futureArg} from '../util/props.js';\nimport "
},
{
"path": "test/unit/2.fork.js",
"chars": 812,
"preview": "import {fork} from '../../index.js';\nimport {testFunction, functionArg, futureArg} from '../util/props.js';\nimport {eq, "
},
{
"path": "test/unit/2.promise.js",
"chars": 950,
"preview": "import {promise} from '../../index.js';\nimport {testFunction, futureArg} from '../util/props.js';\nimport {noop, isThenab"
},
{
"path": "test/unit/2.value.js",
"chars": 817,
"preview": "import show from 'sanctuary-show';\nimport {value} from '../../index.js';\nimport {testFunction, functionArg, resolvedFutu"
},
{
"path": "test/unit/3.after.js",
"chars": 880,
"preview": "import {after, never} from '../../index.js';\nimport {eq, assertValidFuture, assertResolved, test, error} from '../util/u"
},
{
"path": "test/unit/3.attempt-p.js",
"chars": 2405,
"preview": "/* eslint prefer-promise-reject-errors: 0 */\n\nimport chai from 'chai';\nimport {attemptP, map, mapRej} from '../../index."
},
{
"path": "test/unit/3.attempt.js",
"chars": 1043,
"preview": "import chai from 'chai';\nimport {attempt, map} from '../../index.js';\nimport {test, assertCrashed, assertRejected, asser"
},
{
"path": "test/unit/3.cache.js",
"chars": 5772,
"preview": "import chai from 'chai';\nimport {Future, cache, resolve, reject, after, rejectAfter} from '../../index.js';\nimport {Cras"
},
{
"path": "test/unit/3.crash.js",
"chars": 405,
"preview": "import {crash} from '../../src/future.js';\nimport {eq, assertIsFuture, assertCrashed, test} from '../util/util.js';\nimpo"
},
{
"path": "test/unit/3.encase-p.js",
"chars": 1998,
"preview": "/* eslint prefer-promise-reject-errors: 0 */\n\nimport chai from 'chai';\nimport {encaseP} from '../../index.js';\nimport {t"
},
{
"path": "test/unit/3.encase.js",
"chars": 1108,
"preview": "import chai from 'chai';\nimport {encase, map} from '../../index.js';\nimport {test, assertCrashed, assertRejected, assert"
},
{
"path": "test/unit/3.go.js",
"chars": 3174,
"preview": "import chai from 'chai';\nimport {Future, go, resolve, after} from '../../index.js';\nimport {test, assertCrashed, assertR"
},
{
"path": "test/unit/3.hook.js",
"chars": 6541,
"preview": "import chai from 'chai';\nimport {Future, hook, resolve, reject} from '../../index.js';\nimport {test, assertCrashed, asse"
},
{
"path": "test/unit/3.node.js",
"chars": 1645,
"preview": "import chai from 'chai';\nimport {node} from '../../index.js';\nimport {test, assertCrashed, assertRejected, assertResolve"
},
{
"path": "test/unit/3.parallel.js",
"chars": 6693,
"preview": "import chai from 'chai';\nimport {Future, parallel, resolve, reject, after} from '../../index.js';\nimport {test, promiseT"
},
{
"path": "test/unit/3.reject-after.js",
"chars": 932,
"preview": "import {rejectAfter, never} from '../../index.js';\nimport {eq, assertValidFuture, assertRejected, test, error} from '../"
},
{
"path": "test/unit/3.reject.js",
"chars": 514,
"preview": "import {reject} from '../../index.js';\nimport {eq, assertValidFuture, assertRejected, test} from '../util/util.js';\nimpo"
},
{
"path": "test/unit/3.resolve.js",
"chars": 523,
"preview": "import {resolve} from '../../index.js';\nimport {eq, assertValidFuture, assertResolved, test} from '../util/util.js';\nimp"
},
{
"path": "test/unit/4.alt.js",
"chars": 1681,
"preview": "import Either from 'sanctuary-either';\nimport {Future, alt} from '../../index.js';\nimport {assertCrashed, eq, assertVali"
},
{
"path": "test/unit/4.and.js",
"chars": 1459,
"preview": "import {Future, and} from '../../index.js';\nimport {assertCrashed, eq, assertValidFuture, noop, assertResolved, assertRe"
},
{
"path": "test/unit/4.ap.js",
"chars": 1836,
"preview": "import Either from 'sanctuary-either';\nimport {Future, ap, resolve, reject, after} from '../../index.js';\nimport {assert"
},
{
"path": "test/unit/4.bichain.js",
"chars": 1458,
"preview": "import {bichain} from '../../index.js';\nimport {test, assertCrashed, assertRejected, assertResolved, assertValidFuture, "
},
{
"path": "test/unit/4.bimap.js",
"chars": 1073,
"preview": "import Either from 'sanctuary-either';\nimport {bimap} from '../../index.js';\nimport {test, assertCrashed, assertRejected"
},
{
"path": "test/unit/4.both.js",
"chars": 2758,
"preview": "import {Future, both, node, done} from '../../index.js';\nimport {test, assertCrashed, assertRejected, assertResolved, as"
},
{
"path": "test/unit/4.chain-rej.js",
"chars": 1342,
"preview": "import {chainRej, resolve, reject} from '../../index.js';\nimport {test, assertCrashed, assertRejected, assertResolved, a"
},
{
"path": "test/unit/4.chain.js",
"chars": 1463,
"preview": "import Either from 'sanctuary-either';\nimport {chain, resolve, reject} from '../../index.js';\nimport {test, assertCrashe"
},
{
"path": "test/unit/4.coalesce.js",
"chars": 956,
"preview": "import {coalesce} from '../../index.js';\nimport {test, assertCrashed, assertResolved, assertValidFuture, bang, B, throwi"
},
{
"path": "test/unit/4.lastly.js",
"chars": 1850,
"preview": "import {lastly, resolve, reject, map} from '../../index.js';\nimport {test, assertRejected, assertResolved, assertValidFu"
},
{
"path": "test/unit/4.map-rej.js",
"chars": 1203,
"preview": "import {mapRej} from '../../index.js';\nimport {test, assertCrashed, assertRejected, assertResolved, assertValidFuture, b"
},
{
"path": "test/unit/4.map.js",
"chars": 1337,
"preview": "import Either from 'sanctuary-either';\nimport {map} from '../../index.js';\nimport {test, assertCrashed, assertRejected, "
},
{
"path": "test/unit/4.pap.js",
"chars": 1556,
"preview": "import {Future, resolve, reject, after} from '../../index.js';\nimport {pap} from '../../src/pap.js';\nimport {test, asser"
},
{
"path": "test/unit/4.race.js",
"chars": 2651,
"preview": "import {Future, race} from '../../index.js';\nimport {test, assertCrashed, assertRejected, assertResolved, assertValidFut"
},
{
"path": "test/unit/4.swap.js",
"chars": 638,
"preview": "import {swap, resolve, reject} from '../../index.js';\nimport {test, assertRejected, assertResolved, assertValidFuture, e"
},
{
"path": "test/unit/5.chain-rec.js",
"chars": 2514,
"preview": "import chai from 'chai';\nimport {resolve, after, reject} from '../../index.js';\nimport {chainRec} from '../../src/future"
},
{
"path": "test/unit/5.par.js",
"chars": 4017,
"preview": "import chai from 'chai';\nimport Z from 'sanctuary-type-classes';\nimport {Future, Par, seq, resolve, reject, never, ap, m"
},
{
"path": "test/unit/5.seq.js",
"chars": 208,
"preview": "import {seq} from '../../index.js';\nimport {testFunction, parallelArg} from '../util/props.js';\nimport {assertValidFutur"
},
{
"path": "test/util/futures.js",
"chars": 645,
"preview": "import {Future, resolve, reject, after, rejectAfter, and} from '../../index.js';\nimport {crash} from '../../src/future.j"
},
{
"path": "test/util/props.js",
"chars": 4632,
"preview": "import type from 'sanctuary-type-identifiers';\nimport show from 'sanctuary-show';\nimport jsc from 'jsverify';\n\nimport {o"
},
{
"path": "test/util/util.js",
"chars": 4056,
"preview": "import oletus from 'oletus';\nimport show from 'sanctuary-show';\nimport {reject, resolve} from '../../index.js';\nimport {"
}
]
About this extraction
This page contains the full source code of the Avaq/Fluture GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 139 files (383.8 KB), approximately 104.9k tokens, and a symbol index with 497 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.