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
- Host: GitHub
- URL: https://github.com/russellmcc/fantasydo
- Owner: russellmcc
- Created: 2014-01-18T20:56:58.000Z (almost 12 years ago)
- Default Branch: master
- Last Pushed: 2014-01-18T21:01:02.000Z (almost 12 years ago)
- Last Synced: 2025-06-23T03:48:12.416Z (5 months ago)
- Language: JavaScript
- Size: 121 KB
- Stars: 64
- Watchers: 1
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-functional-programming - **fantasydo** - Do-notation for javascript fantasy land
- awesome-functional-programming - **fantasydo** - Do-notation for javascript fantasy land
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).

## 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
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.