// 參考 // http://jiyinyiyong.github.io/monads-in-pictures/ // https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/ch8.html // https://zhuanlan.zhihu.com/p/21926955 // https://zhuanlan.zhihu.com/p/22094473 // functor就是一個容器 var Container = function(x) { this.__value = x; } Container.of = function(x) { return new Container(x); }; Container.of(3); // map函數的參數是一個函數。這個函數用來運算容器裏面的值。 Container.prototype.map = function(f){ return Container.of(f(this.__value)) }; Container.of(2).map(function(two){ return two + 2 }).map(function(num){return num * 2 }); // 高級一點的functor,能夠處理null的functor。 var Maybe = function(x) { this.__value = x; }; Maybe.of = function(x) { return new Maybe(x); }; Maybe.prototype.isNothing = function() { return (this.__value === null || this.__value === undefined); }; Maybe.prototype.map = function(f) { return this.isNothing() ? Maybe.of(null) : Maybe.of(f(this.__value)); }; Maybe.prototype.join = function() { return this.isNothing() ? Maybe.of(null) : this.__value; } Maybe.of({name: "Boris"}).map(function(obj){return obj['age'] }).map(function(num){return num + 10}); Maybe.of(3).map(function(num){return num + 2; }).map(function(num){return num + 5}); console.log('點的連續運算', Maybe.of(3).map(function(num){return num + 2; }).map(function(num){return num + 5}) ); console.log('函數組合',Maybe.of(function(num){return num + 2}).map(function(num){return num + 3})); // 儘管Maybe會返回null,可是咱們不知道它從哪返回,也沒有更多異常信息。 // 錯誤捕獲 var Left = function(x) { this.__value = x; } var Right = function(x) { this.__value = x; } Left.of = function(x) { return new Left(x); }; Right.of = function(x) { return new Right(x); }; Left.prototype.map = function(f) { return this; }; Right.prototype.map = function(f) { return Right.of(f(this.__value)); }; var either = function(f, g, e) { switch(e.constructor) { case Left: return f(e.__value); case Right: return g(e.__value); } }; var a = Maybe.of({name: "Boris"}).map(function(obj){ if(obj['name']){return Right.of('has age')} else{ return Left.of('no age'); } }) // .map(function(num){return num + 10}).map(function(num){return num + 1}); console.log('a',a); // 另類functor,惰性求值,用來接觸外面的世界。把反作用操做( IO操做、異步請求、DOM操做)包裹起來。 var IO = function(f) { this.__value = f; }; IO.of = function(x) { return new IO(function() { return x; }); }; IO.prototype.map = function(f) { return new IO(f(this.__value)); }; // 能夠鏈式調用。 // 能夠進行函數組合。 // 處理反作用。常見的反作用包括異常和異步。 // 咱們很快想到數組也是一個容器functor,該容器的map函數也是用來運算容器裏面的值。 // promise也是一個容器functor。 // Applicative是一個起子,用來打開容器。 // 把容器裏的函數應用到容器裏的值。