Skip to content

Instantly share code, notes, and snippets.

@Davis-Desormeaux
Forked from liquidz/monad.js
Created April 20, 2012 04:16
Show Gist options
  • Save Davis-Desormeaux/2425979 to your computer and use it in GitHub Desktop.
Save Davis-Desormeaux/2425979 to your computer and use it in GitHub Desktop.
monad.js: checking with rhino
// checking with rhino
(function(){
// MonadBase {{{
var MonadBase = function(){};
MonadBase.prototype.result = function(v){
return function(){ return v; };
};
MonadBase.prototype.bind = function(a, f){
return f(a());
};
MonadBase.prototype.chainFn = function(a){
var self = this;
return function(f){
return self.chain(self.bind(a, function(v){
return self.result(f(v));
}));
};
};
MonadBase.prototype.chainVal = function(a){
return function(){
return a();
};
};
MonadBase.prototype.optionalChain = function(a, chainBase){ return chainBase; };
MonadBase.prototype.chain = function(a){
return this.optionalChain(a, {
fn: this.chainFn(a),
val: this.chainVal(a)
});
};
// }}}
// == IdentityMonad {{{
var IdentityMonad = function(){};
IdentityMonad.prototype = new MonadBase();
// }}}
// == MaybeMonad {{{
var MaybeMonad = function(){};
MaybeMonad.prototype = new MonadBase();
MaybeMonad.prototype.bind = function(a, f){
var v = a();
if(v === null || v === undefined){
return this.result(null);
} else {
return f(v);
}
};
// }}}
// == StateMonad {{{
var StateMonad = function(){};
StateMonad.prototype = new MonadBase();
StateMonad.prototype.result = function(v){
return function(state){
return [v, state];
};
};
StateMonad.prototype.bind = function(a, f){
return function(state){
var arr = a(state), v = arr[0], newState = arr[1];
return f(v)(newState);
};
};
StateMonad.prototype.setValue = function(v){
return function(s){
return [v, v];
};
};
StateMonad.prototype.optionalChain = function(a, base){
var self = this;
base.state = function(s){
return self.chain(self.bind(a, function(v){
return self.bind(self.setValue(s), function(x){
return self.result(v);
});
}));
};
return base;
};
StateMonad.prototype.chainVal = function(a){
return function(state){
return a(state);
};
};
// }}}
// == ListMonad {{{
var ListMonad = function(){};
ListMonad.prototype = new MonadBase();
ListMonad.prototype.result = function(v){
return [v];
};
ListMonad.prototype.map = function(arr, f){
var i = 0, l = arr.length, result = [];
for(i = 0; i < l; ++i){
result.push(f(arr[i]));
}
return result;
};
ListMonad.prototype.concat = function(){
var i = 0, l = arguments.length, result = arguments[0];
for(i = 1; i < l; ++i){
result = result.concat(arguments[i]);
}
return result;
};
ListMonad.prototype.bind = function(arr, f){
return this.concat.apply(this, this.map(arr, f));
};
ListMonad.prototype.chainVal = function(a){
return function(){ return a; };
};
// }}}
var inc = function(v){ return((v === null) ? NaN : v + 1); };
var nil = function(x){ return null; };
print("> identity monad");
var im = new IdentityMonad();
print(im.chain(im.result(1)).fn(inc).fn(inc).val());
print(im.chain(im.result(1)).fn(nil).fn(inc).val());
print("");
print("> maybe monad");
var mm = new MaybeMonad();
print(mm.chain(mm.result(1)).fn(inc).fn(inc).val());
print(mm.chain(mm.result(1)).fn(nil).fn(inc).val());
print("");
print("> state monad");
var sm = new StateMonad();
print(sm.chain(sm.result(1)).fn(inc).fn(inc).val("init"));
print(sm.chain(sm.result(1)).fn(inc).state("hoge").fn(inc).val("init"));
print("");
print("> list monad");
var lm = new ListMonad();
print(lm.chain([1, 2, 3]).fn(inc).fn(inc).val());
print(lm.bind([1, 2, 3], function(x){
return lm.bind([10, 20, 30], function(y){
return lm.result(x + y);
});
}));
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment