Created
April 2, 2011 14:23
-
-
Save liquidz/899523 to your computer and use it in GitHub Desktop.
monad.js: checking with rhino
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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