monads-co
Version:
An implementation of Haskell's type classes in TS
163 lines • 4.23 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Maybe = exports.None = exports.Some = exports.Optional = void 0;
const Monad_1 = require("./Monad");
class Optional extends Monad_1.Monad {
_success;
_value;
constructor(_success, _value) {
super();
this._success = _success;
this._value = _value;
}
/**
* Used to wrap a function that can potentially return null or undefined in a safe wrapper
* ```ts
* const safeQuerySelector = Optional.wrap(document.querySelector)
* ```
* @param fn
*/
static wrap(fn) {
return (...args) => {
const out = fn(...args);
if (out === undefined || out === null) {
return None();
}
else {
return Some(out);
}
};
}
/**
* If a value is held, this uses the mapping function to transform it, and returns Optional<New Value>
* otherwise, it returns None()
* @param mapping
*/
map(mapping) {
if (this._success) {
return Some(mapping(this._value));
}
else {
return None();
}
}
amap(mapping) {
if (this._success) {
if (mapping._success) {
return Some(mapping._value(this._value));
}
return None();
}
return None();
}
pure(value) {
return Some(value);
}
/**
* If a value is held the mapping is preformed on it, otherwise None() is returned. If you want to just transform
* ValueT to a new Value, use `.map`
* @param mapping
*/
then(mapping) {
if (this._success) {
return mapping(this._value);
}
return None();
}
// Result specific methods
/**
* Returns the value is defined, otherwise it returns `defaultValue`
* @param defaultValue
*/
or(defaultValue) {
if (this._success) {
return this._value;
}
return defaultValue;
}
/**
* If None() replace it with a value
* @param mapping
*/
catch(mapping) {
if (this._success) {
return Some(this._value);
}
return Some(mapping());
}
/**
* If None() replaces it with the result of the mapping
* @param mapping
*/
catchThen(mapping) {
if (this._success) {
return Some(this._value);
}
return mapping();
}
/**
* Returns the value if Some(), otherwise it throws a reference error.
* This is the nuclear option, `.or(default)` should be preferred.
*/
unwrap() {
if (this._success) {
return this._value;
}
// Kaboom, functional land just died :(
throw new ReferenceError("When Optional<T> was unwrapped, no value was found");
}
}
exports.Optional = Optional;
/**
* Used to construct Some value, for example:
*
* @example
* ```ts
* // Gets all but the start of the string; IE "string" -> "tring"
* function getStringTail(input: string): Optional<string> {
* if (input.length <= 1) {
* return None()
* } else {
* return Some(input.slice(1))
* }
* }
* ```
* @param value
*/
function Some(value) {
return new Optional(true, value);
}
exports.Some = Some;
/**
* Used to construct Some value, for example:
*
* @example
* ```ts
* // Gets all but the start of the string; IE "string" -> "tring"
* function getStringTail(input: string): Optional<string> {
* if (input.length <= 1) {
* return None()
* } else {
* return Some(input.slice(1))
* }
* }
* ```
*/
function None() {
return new Optional(false, null);
}
exports.None = None;
/**
* Like Some() or None() but it doesn't mind if you give it a value or not.
* @param value
*/
function Maybe(value) {
if (value) {
return Some(value);
}
else {
return None();
}
}
exports.Maybe = Maybe;
//# sourceMappingURL=Optional.js.map