An open API service indexing awesome lists of open source software.

https://github.com/russellmcc/fantasydo

Do-notation for javascript fantasy land
https://github.com/russellmcc/fantasydo

Last synced: 4 months ago
JSON representation

Do-notation for javascript fantasy land

Awesome Lists containing this project

README

          

# Fantasy Do

Fantasy do is a generalization of mozilla's [`task.js`](http://taskjs.org/) from [Promises/A+](http://promises-aplus.github.io/promises-spec/) to any monad, as defined by the [Fantasy Land Spec](https://raw.github.com/fantasyland/fantasy-land/). While usage is syntactically similar to Haskell's Do Notation, it's implemented completely at runtime with [ES6 generators](http://wiki.ecmascript.org/doku.php?id=harmony:generators).

![Fantasy Land Branding](https://raw.github.com/fantasyland/fantasy-land/master/logo.png)

## Usage

Fantasy Do requires ES6 generators. In node, you can enable these with the `--harmony` option.

If you happen to have a browser with ES6 support, use the included `fantasydo.min.js` with your [module loader of choice](https://github.com/forbeslindesay/umd), or just with a `script` tag.

The library is available for `node.js` on `npm` under `fantasydo`

### Normal mode

If your monad only calls the argument to the `chain` function once ('non-branching'), you can use Fantasy Do's normal, high-performance mode.

First, you'll need a monad. See the [Fantasy Land Implementation List](https://github.com/fantasyland/fantasy-land/blob/master/implementations.md) to find some monads that may work for you.

Here's a very simple `Maybe` monad:

var Maybe = {}
Maybe.chain = function(f) {
if(this.val !== null)
return f(this.val);
return this;
};
Maybe.of = function(t) {
return {"val" : t, "chain" : Maybe.chain};
};
Maybe.none = function() {
return {"val" : null, "chain" : Maybe.chain};
};

Now, we can write a function that depends on multiple maybe values, and will only complete if all of them are not `none`:

Do(function*(){
var a = yield Maybe.of(7);
var b = yield Maybe.of(a + 9);
return b;
}, Maybe).val; // => 16

Do(function*(){
var a = yield Maybe.of(7);
var q = yield Maybe.none();
var b = yield Maybe.of(a + 9);
return b;
}, Maybe).val; // => null

### Multi-mode

Fantasy Do also supports monads that may call their `chain` parameter multiple times, like the non-determinism context (aka the list monad). Without the ability to copy generator state, this works by re-runninng the generator from the beginning for each branch. This may behave strangely if your bind argument has significant side-effects.

Array.prototype.chain = function(f) {
let next = [];
let len = this.length;
this.forEach(function(it){
let v = f(it);
v.forEach(function(it){next.push(it)});
});
return next;
};
Array.prototype.of = function(t) {return [t];}

then,

Do.Multi(function*(){
let c = yield [1, 2];
let d = yield [c + 1, c + 2];
return d;
}, Array.prototype); // => [2, 3, 3, 4]

## License



CC0



To the extent possible under law,

Russell McClellan

has waived all copyright and related or neighboring rights to
Fantasy Do.
This work is published from:

United States
.