-
-
Save piq9117/5d79c0ab5b53412f72c806d7563a56a4 to your computer and use it in GitHub Desktop.
JavaScript Maybe monad
This file contains 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
module.exports = Maybe; | |
function Maybe(x) { | |
this._value = x; | |
} | |
Maybe.of = of; | |
Maybe.empty = empty; | |
var nothingValue = void 0; | |
var nothing = Maybe.nothing = new Maybe(nothingValue); | |
function of(x) { | |
return new Maybe(x); | |
} | |
function empty() { | |
// For Semigroup/Monoid | |
return nothing; | |
} | |
Maybe.catMaybes = function(list) { | |
return list.reduce(function(justs, maybe) { | |
if(maybe.isJust()) { | |
justs.push(maybe); | |
} | |
return justs; | |
}, []); | |
}; | |
Maybe.mapMaybes = function(f, list) { | |
return list.reduce(function(justs, maybe) { | |
var mappedMaybe = maybe.map(f); | |
if(mappedMaybe.isJust()) { | |
justs.push(mappedMaybe); | |
} | |
return justs; | |
}, []); | |
}; | |
Maybe.prototype.isNothing = function() { | |
return this._value === nothingValue; | |
}; | |
Maybe.prototype.isJust = function() { | |
return !this.isNothing(); | |
}; | |
Maybe.prototype.map = function(f) { | |
return this.isNothing() ? this : of(f(this._value)); | |
}; | |
Maybe.prototype.ap = function(maybe) { | |
return this.flatMap(function(f) { | |
return maybe.map(f); | |
}); | |
}; | |
Maybe.prototype.flatMap = function(f) { | |
return this.isNothing() ? this : f(this._value); | |
}; | |
Maybe.prototype.concat = function(maybe) { | |
// Semigroup/Monoid | |
// See http://en.wikibooks.org/wiki/Haskell/MonadPlus#Definition | |
return this.isNothing() ? maybe : this; | |
}; | |
Maybe.prototype.filter = function(predicate) { | |
return this.isJust() && predicate(this._value) ? this : nothing; | |
}; | |
Maybe.prototype.maybe = function(f, defaultValue) { | |
return this.isNothing() ? defaultValue : f(this._value); | |
}; | |
Maybe.prototype.fromMaybe = function(defaultValue) { | |
return this.isNothing() ? defaultValue : this._value; | |
}; | |
Maybe.prototype.fromJust = function() { | |
if(this.isNothing()) { | |
throw new TypeError('fromJust: Maybe is nothing'); | |
} | |
return this._value; | |
}; | |
Maybe.prototype.foldl = Maybe.prototype.foldr = function(f, initial) { | |
return this.isNothing() ? initial : f(initial, this._value); | |
}; | |
Maybe.prototype.foldl1 = Maybe.prototype.foldr1 = function(f) { | |
return this.fromJust(); | |
} | |
Maybe.prototype.reduce = function(f) { | |
return arguments.length < 2 ? this.foldl1(f) : this.foldl(f, arguments[1]); | |
}; | |
Maybe.prototype.reduceRight = function(f) { | |
return arguments.length < 2 ? this.foldr1(f) : this.foldr(f, arguments[1]); | |
}; | |
Maybe.prototype.listToMaybe = function(list) { | |
return list.length === 0 ? nothing : of(list[0]); | |
}; | |
Maybe.prototype.maybeToList = function() { | |
return this.isNothing() ? [] : [this._value]; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment