maybetyped
Version:
Well-typed functional Maybe monad
212 lines (198 loc) • 6.88 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
// TODO: remove this if fantasy-land exports own types
var map = 'fantasy-land/map';
var ap = 'fantasy-land/ap';
var of = 'fantasy-land/of';
var chain = 'fantasy-land/chain';
var _a, _b, _c;
var binder = function (context, f) { return f.bind(context); }; // tslint:disable-line ban-types
var isNothing = function (thing) {
return thing === undefined || thing === null;
};
var Maybe = /** @class */ (function () {
function Maybe(value) {
var _this = this;
this.value = value;
this[_a] = binder(this, this.map);
this[_b] = binder(this, this.flatMap);
this[_c] = function (m) { return m.flatMap(function (f) { return _this.map(f); }); };
}
Maybe.prototype.isNothing = function () { return isNothing(this.value); };
return Maybe;
}());
_a = map, _b = chain, _c = ap;
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var Some = /** @class */ (function (_super) {
__extends(Some, _super);
function Some() {
return _super !== null && _super.apply(this, arguments) || this;
}
Some.some = function (thing) { return new Some(thing); };
Some.prototype.expect = function () { return this.value; };
Some.prototype.caseOf = function (funcs) {
return funcs.some
? maybe(funcs.some(this.value))
: none();
};
Some.prototype.map = function (f) {
return maybe(f(this.value));
};
Some.prototype.tap = function (f) {
f(this.value);
return this;
};
Some.prototype.flatMap = function (f) {
return f(this.value);
};
Some.prototype.orElse = function (def) {
return this.value;
};
Some.prototype.or = function (other) {
return this;
};
Some.prototype.eq = function (other) {
var _this = this;
return other.map(function (v) { return v === _this.value; })
.orElse(false);
};
Some.prototype.join = function (f, other) {
return this.flatMap(function (x) { return other.map(function (y) { return f(x, y); }); });
};
Some.prototype.asNullable = function () {
return this.value;
};
return Some;
}(Maybe));
var some = Some.some;
var isNoArgFunc = function (x) {
return typeof x === "function" && x.length === 0;
};
var invokeFunc = function (funcOrT) {
if (isNoArgFunc(funcOrT)) {
return funcOrT();
}
return funcOrT;
};
var None = /** @class */ (function (_super) {
__extends(None, _super);
function None() {
return _super.call(this, null) || this;
}
None.none = function () { return new None(); };
None.prototype.expect = function (msg) {
if (msg instanceof Error)
throw msg;
throw new Error(msg || 'Expected Maybe to contain non-null value');
};
None.prototype.caseOf = function (funcs) {
return funcs.none ?
maybe(funcs.none()) :
this;
};
None.prototype.map = function () {
return this;
};
None.prototype.tap = function () {
return this;
};
None.prototype.flatMap = function () {
return this;
};
None.prototype.orElse = function (def) {
return invokeFunc(def);
};
None.prototype.or = function (other) {
return invokeFunc(other);
};
None.prototype.eq = function (other) {
return other instanceof None;
};
None.prototype.join = function (f, other) {
return this;
};
None.prototype.asNullable = function () { return null; };
return None;
}(Maybe));
var _noneSingleton = None.none();
var none = function () { return _noneSingleton; };
var isPromise = function (x) { return typeof x.then === 'function'; };
var getMap = function (x) {
if (isPromise(x))
return x.then.bind(x);
return x.map.bind(x);
};
var MaybeT = /** @class */ (function () {
function MaybeT(value) {
this.value = value;
}
MaybeT.maybeT = function (monad) {
return new MaybeT(monad);
};
MaybeT.prototype.map = function (f) {
var map = getMap(this.value);
return new MaybeT(map(function (inner) {
return maybe(inner)
.map(f)
.asNullable();
}));
};
MaybeT.prototype.caseOf = function (matcher) {
var map = getMap(this.value);
return new MaybeT(map(function (inner) {
return maybe(inner)
.caseOf(matcher)
.asNullable();
}));
};
MaybeT.prototype.orElse = function (def) {
var map = getMap(this.value);
return map(function (inner) {
return maybe(inner)
.orElse(def);
});
};
MaybeT.prototype.asNullable = function () { return this.value; };
MaybeT.prototype.asType = function (c) {
if (!(this.value instanceof c))
throw new Error("Expected value to be instance of monad " + c.name);
return this.value;
};
return MaybeT;
}());
var maybeT = MaybeT.maybeT;
var maybe = function (value) { return isNothing(value)
? none()
: some(value); };
// gotta do this here to get around circular imports
Maybe.of = maybe;
Maybe[of] = maybe;
exports.MaybeT = MaybeT;
exports.default = Maybe;
exports.maybe = maybe;
exports.maybeT = maybeT;
exports.none = none;
exports.some = some;