1372 lines
30 KiB
JavaScript
1372 lines
30 KiB
JavaScript
(() => {
|
|
// src/mixin.js
|
|
var _appliedMixin = "__mixwith_appliedMixin";
|
|
var apply = (superclass, mixin) => {
|
|
let application = mixin(superclass);
|
|
application.prototype[_appliedMixin] = unwrap(mixin);
|
|
return application;
|
|
};
|
|
var isApplicationOf = (proto, mixin) => proto.hasOwnProperty(_appliedMixin) && proto[_appliedMixin] === unwrap(mixin);
|
|
var hasMixin = (o, mixin) => {
|
|
while (o != null) {
|
|
if (isApplicationOf(o, mixin)) return true;
|
|
o = Object.getPrototypeOf(o);
|
|
}
|
|
return false;
|
|
};
|
|
var _wrappedMixin = "__mixwith_wrappedMixin";
|
|
var wrap = (mixin, wrapper) => {
|
|
Object.setPrototypeOf(wrapper, mixin);
|
|
if (!mixin[_wrappedMixin]) {
|
|
mixin[_wrappedMixin] = mixin;
|
|
}
|
|
return wrapper;
|
|
};
|
|
var unwrap = (wrapper) => wrapper[_wrappedMixin] || wrapper;
|
|
var _cachedApplications = "__mixwith_cachedApplications";
|
|
var Cached = (mixin) => wrap(mixin, (superclass) => {
|
|
let cachedApplications = superclass[_cachedApplications];
|
|
if (!cachedApplications) {
|
|
cachedApplications = superclass[_cachedApplications] = /* @__PURE__ */ new Map();
|
|
}
|
|
let application = cachedApplications.get(mixin);
|
|
if (!application) {
|
|
application = mixin(superclass);
|
|
cachedApplications.set(mixin, application);
|
|
}
|
|
return application;
|
|
});
|
|
var DeDupe = (mixin) => wrap(mixin, (superclass) => hasMixin(superclass.prototype, mixin) ? superclass : mixin(superclass));
|
|
var BareMixin = (mixin) => wrap(mixin, (s) => apply(s, mixin));
|
|
var Mixin = (mixin) => DeDupe(Cached(BareMixin(mixin)));
|
|
var mix = (superclass) => new MixinBuilder(superclass);
|
|
var MixinBuilder = class {
|
|
constructor(superclass) {
|
|
this.superclass = superclass || class {
|
|
};
|
|
}
|
|
/**
|
|
* Applies `mixins` in order to the superclass given to `mix()`.
|
|
*
|
|
* @param {Array.<MixinFunction>} mixins
|
|
* @return {FunctionConstructor} a subclass of `superclass` with `mixins` applied
|
|
*/
|
|
with(...mixins) {
|
|
return mixins.reduce((c, m) => m(c), this.superclass);
|
|
}
|
|
};
|
|
|
|
// src/algebra/interfaces.js
|
|
var ProtectedConstructor = Symbol("ProtectedConstructor");
|
|
var NotImplementedError = class extends Error {
|
|
/** @param {string} name */
|
|
constructor(name) {
|
|
super(`${name} is not implemented`);
|
|
}
|
|
};
|
|
var MethodType = Object.freeze({
|
|
Instance: 0,
|
|
Static: 1
|
|
});
|
|
var Method = class _Method {
|
|
#name;
|
|
/** @type {MethodType} */
|
|
#type = MethodType.Instance;
|
|
/** @type {Fn} */
|
|
#implementation;
|
|
/**
|
|
* @param {string | Method} name
|
|
*/
|
|
constructor(name) {
|
|
if (name instanceof _Method) {
|
|
return name;
|
|
}
|
|
this.#name = name;
|
|
}
|
|
/**
|
|
* @param {string | Method} value
|
|
*/
|
|
static from(value) {
|
|
return new _Method(value);
|
|
}
|
|
isInstance() {
|
|
this.#type = MethodType.Instance;
|
|
return this;
|
|
}
|
|
isStatic() {
|
|
this.#type = MethodType.Static;
|
|
return this;
|
|
}
|
|
/** @param {Fn} f */
|
|
implementation(f) {
|
|
this.#implementation = f;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param {string} interfaceName
|
|
*/
|
|
_defaultImplementation(interfaceName) {
|
|
const err2 = new NotImplementedError(
|
|
`${interfaceName}::${this.#name}`
|
|
);
|
|
return function() {
|
|
throw err2;
|
|
};
|
|
}
|
|
/**
|
|
* @param {Function} target
|
|
*/
|
|
_getInstallationPoint(target) {
|
|
switch (this.#type) {
|
|
case 0:
|
|
return Object.getPrototypeOf(target);
|
|
case 1:
|
|
return target;
|
|
default:
|
|
return target;
|
|
}
|
|
}
|
|
/**
|
|
* @param {Interface} builder
|
|
* @param {Function} target
|
|
*/
|
|
implement(builder, target) {
|
|
const impl = this.#implementation || this._defaultImplementation(builder.name);
|
|
this._getInstallationPoint(target)[this.#name] = impl;
|
|
}
|
|
};
|
|
var Implementations = Symbol();
|
|
var Interface = class {
|
|
#name;
|
|
/** @type {MixinFunction} */
|
|
#mixin;
|
|
/** @type {Set<Method>} */
|
|
#methods = /* @__PURE__ */ new Set();
|
|
/** @type {Set<Interface>} */
|
|
#interfaces = /* @__PURE__ */ new Set();
|
|
/** @param {string} name */
|
|
constructor(name) {
|
|
this.#name = name;
|
|
this.#mixin = Mixin(this.build.bind(this));
|
|
}
|
|
get name() {
|
|
return this.#name;
|
|
}
|
|
findInterfaces(type) {
|
|
let interfaces = /* @__PURE__ */ new Set();
|
|
let current = type;
|
|
while (current != null) {
|
|
interfaces = new Set(current[Implementations]).union(interfaces);
|
|
current = Object.getPrototypeOf(current);
|
|
}
|
|
return interfaces;
|
|
}
|
|
/**
|
|
* @param {{ name: string }} type
|
|
* @returns {boolean}
|
|
*/
|
|
implementedBy(type) {
|
|
return this.findInterfaces(type).has(this);
|
|
}
|
|
/**
|
|
* @param {...(PropertyKey | Method)} methods
|
|
* @returns {this}
|
|
*/
|
|
specifies(...methods) {
|
|
this.#methods = new Set(
|
|
methods.map(Method.from).concat(...this.#methods)
|
|
);
|
|
return this;
|
|
}
|
|
/**
|
|
* @param {...Interface} interfaces
|
|
* @returns {this}
|
|
*/
|
|
extends(...interfaces) {
|
|
this.#interfaces = new Set(interfaces.concat(...this.#interfaces));
|
|
return this;
|
|
}
|
|
/**
|
|
* @returns {MixinFunction}
|
|
*/
|
|
asMixin() {
|
|
return this.#mixin;
|
|
}
|
|
/**
|
|
* @param {FunctionConstructor} base
|
|
*/
|
|
build(base) {
|
|
const interfaces = [...this.#interfaces.values()];
|
|
const mixins = interfaces.map((x) => x.asMixin());
|
|
const Interfaces5 = mix(base).with(...mixins);
|
|
const Algebra2 = class extends Interfaces5 {
|
|
};
|
|
for (const method of this.#methods) {
|
|
method.implement(this, Algebra2);
|
|
}
|
|
const prototype = Object.getPrototypeOf(Algebra2);
|
|
prototype[Implementations] = new Set(interfaces);
|
|
return Algebra2;
|
|
}
|
|
};
|
|
var BaseSet = class {
|
|
};
|
|
var AlgebraWithBase = (base) => (...algebras) => {
|
|
return mix(base).with(...algebras.map((x) => x.asMixin()));
|
|
};
|
|
var Algebra = AlgebraWithBase(BaseSet);
|
|
var Setoid = new Interface("Setoid").specifies("equals");
|
|
var Ord = new Interface("Ord").specifies("lte");
|
|
var Semigroupoid = new Interface("Semigroupoid").specifies("compose");
|
|
var Category = new Interface("Category").extends(Semigroupoid).specifies(
|
|
Method.from("id").isStatic()
|
|
);
|
|
var Semigroup = new Interface("Semigroup").specifies("concat");
|
|
var Monoid = new Interface("Monoid").extends(Semigroup).specifies(
|
|
Method.from("empty").isStatic()
|
|
);
|
|
var Group = new Interface("Group").extends(Monoid).specifies("invert");
|
|
var Filterable = new Interface("Filterable").specifies("filter");
|
|
var Functor = new Interface("Functor").specifies("map");
|
|
var Contravariant = new Interface("Contravariant").specifies("contramap");
|
|
var Apply = new Interface("Apply").extends(Functor).specifies("ap");
|
|
var Applicative = new Interface("Applicative").extends(Apply).specifies(
|
|
Method.from("of").isStatic()
|
|
);
|
|
var Alt = new Interface("Alt").extends(Functor).specifies("alt");
|
|
var Plus = new Interface("Plus").extends(Alt).specifies(
|
|
Method.from("zero").isStatic()
|
|
);
|
|
var Alternative = new Interface("Alternative").extends(Applicative, Plus);
|
|
var Foldable = new Interface("Foldable").specifies("fold");
|
|
var Traversable = new Interface("Traversable").extends(Functor, Foldable).specifies("traverse");
|
|
var Chain = new Interface("Chain").extends(Apply).specifies(
|
|
Method.from("chain").implementation(function(f) {
|
|
return f(this._value);
|
|
})
|
|
);
|
|
var ChainRef = new Interface("ChainRec").extends(Chain).specifies(
|
|
Method.from("chainRec").isStatic()
|
|
);
|
|
var Monad = new Interface("Monad").extends(Applicative, Chain);
|
|
var Extend = new Interface("Extend").extends(Functor).specifies("extend");
|
|
var Comonad = new Interface("Comonad").extends(Extend).specifies("extract");
|
|
var Bifunctor = new Interface("Bifunctor").extends(Functor).specifies("bimap");
|
|
var Profunctor = new Interface("Profunctor").extends(Functor).specifies("promap");
|
|
|
|
// src/algebra/identity.js
|
|
var Identity = class extends Algebra(Monad, Comonad) {
|
|
#value;
|
|
/**
|
|
* @param {T} value
|
|
*/
|
|
constructor(value) {
|
|
super();
|
|
this.#value = value;
|
|
}
|
|
/**
|
|
* @template T
|
|
* @param {T} value
|
|
*/
|
|
static of(value) {
|
|
return id(value);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Functor<T>['map']}
|
|
* @param {Morphism<T, U>} f
|
|
* @returns {Identity<U>}
|
|
*/
|
|
map(f) {
|
|
return id(f(this.#value));
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Apply<T>['ap']}
|
|
* @param {Apply<Morphism<T, U>>} b
|
|
* @returns {Apply<U>}
|
|
*/
|
|
ap(b) {
|
|
return (
|
|
/** @type {Apply<U>} */
|
|
b.map((f) => f(this.#value))
|
|
);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @param {Morphism<T, Identity<U>>} f
|
|
*/
|
|
chain(f) {
|
|
return f(this.#value);
|
|
}
|
|
/**
|
|
* @param {(value: Identity<T>) => T} f
|
|
*/
|
|
extend(f) {
|
|
return id(f(this));
|
|
}
|
|
extract() {
|
|
return this.#value;
|
|
}
|
|
toString() {
|
|
return `Identity(${this.#value})`;
|
|
}
|
|
};
|
|
var id = (value) => new Identity(value);
|
|
|
|
// src/algebra/option.js
|
|
var Interfaces = Algebra(Setoid, Alternative, Monad, Foldable);
|
|
var Some = class _Some extends Interfaces {
|
|
/** @type {T} */
|
|
#value;
|
|
/** @param {T} value */
|
|
constructor(value) {
|
|
super();
|
|
this.#value = value;
|
|
}
|
|
/**
|
|
* @type {SetoidT<T>['equals']}
|
|
* @param {Some<T>} other
|
|
*/
|
|
equals(other) {
|
|
if (other instanceof _Some) {
|
|
return false;
|
|
}
|
|
const eq = (
|
|
/** @type {Some<T>} */
|
|
other.chain((v) => id(v === this.#value))
|
|
);
|
|
return (
|
|
/** @type {Identity<boolean>} */
|
|
eq.extract()
|
|
);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Apply<T>['ap']}
|
|
* @param {Some<Morphism<T, U>>} b
|
|
* @returns {Some<U>}
|
|
*/
|
|
ap(b) {
|
|
return (
|
|
/** @type {Some<U>} */
|
|
b.chain(
|
|
(f) => (
|
|
/** @type {Some<U>} */
|
|
this.map(f)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
/**
|
|
* @type {Alt<T>['alt']}
|
|
*/
|
|
alt(b) {
|
|
return this;
|
|
}
|
|
/**
|
|
* @type {Chain<T>['chain']}
|
|
*/
|
|
chain(f) {
|
|
return f(this.#value);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Functor<T>['map']}
|
|
* @param {Morphism<T, U>} f
|
|
* @returns {Some<U>}
|
|
*/
|
|
map(f) {
|
|
return (
|
|
/** @type {Some<U>} */
|
|
this.chain((v) => some(f(v)))
|
|
);
|
|
}
|
|
/**
|
|
* @type {Functor<T>['map']}
|
|
*/
|
|
then(f) {
|
|
return this.map(f);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {FoldableT<T>['reduce']}
|
|
* @param {(acc: U, value: T) => U} f
|
|
* @param {U} init
|
|
* @returns {U}
|
|
*/
|
|
reduce(f, init) {
|
|
return f(init, this.#value);
|
|
}
|
|
toString() {
|
|
return `Some(${this.#value})`;
|
|
}
|
|
};
|
|
var None = class extends Interfaces {
|
|
/**
|
|
* @type {SetoidT<T>['equals']}
|
|
*/
|
|
equals(other) {
|
|
return other === none;
|
|
}
|
|
/**
|
|
* @type {Apply<T>['ap']}
|
|
* @returns {this}
|
|
*/
|
|
ap(_b) {
|
|
return this;
|
|
}
|
|
/**
|
|
* @type {Alt<T>['alt']}
|
|
*/
|
|
alt(b) {
|
|
return b;
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Chain<T>['chain']}
|
|
* @param {Morphism<T, U>} _f
|
|
* @returns {this}
|
|
*/
|
|
chain(_f) {
|
|
return this;
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Functor<T>['map']}
|
|
* @param {Morphism<T, U>} _f
|
|
* @returns {this}
|
|
*/
|
|
map(_f) {
|
|
return this;
|
|
}
|
|
/**
|
|
* @template R
|
|
* @type {Functor<T>['map']}
|
|
* @param {Morphism<T, R>} _f
|
|
* @returns {None}
|
|
*/
|
|
then(_f) {
|
|
return this;
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {FoldableT<T>['reduce']}
|
|
* @param {(acc: U, value: T) => U} _f
|
|
* @param {U} init
|
|
* @returns {U}
|
|
*/
|
|
reduce(_f, init) {
|
|
return init;
|
|
}
|
|
toString() {
|
|
return "None";
|
|
}
|
|
};
|
|
var some = (value) => new Some(value);
|
|
var none = new None();
|
|
var TypeRef = some;
|
|
TypeRef.constructor["of"] = some;
|
|
TypeRef.constructor["zero"] = none;
|
|
|
|
// src/algebra/result.js
|
|
var Interfaces2 = Algebra(Setoid, Alternative, Monad, Foldable, Bifunctor);
|
|
var Ok = class _Ok extends Interfaces2 {
|
|
/** @type {T} */
|
|
#value;
|
|
/**
|
|
* @param {T} value
|
|
* @constructs {Ok<T, E>}
|
|
*/
|
|
constructor(value) {
|
|
super();
|
|
this.#value = value;
|
|
}
|
|
/**
|
|
* @type {SetoidT<T>['equals']}
|
|
* @param {Result<T, E>} other
|
|
* @returns {boolean}
|
|
*/
|
|
equals(other) {
|
|
if (!(other instanceof _Ok)) {
|
|
return false;
|
|
}
|
|
const eq = other.chain((v) => id(v === this.#value));
|
|
return (
|
|
/** @type {Identity<boolean>} */
|
|
eq.extract()
|
|
);
|
|
}
|
|
/** @returns {this is Ok<T, E>} */
|
|
isOk() {
|
|
return true;
|
|
}
|
|
/** @returns {this is Err<T, E>} */
|
|
isErr() {
|
|
return false;
|
|
}
|
|
/**
|
|
* @type {Chain<T>['chain']}
|
|
*/
|
|
chain(f) {
|
|
return f(this.#value);
|
|
}
|
|
/**
|
|
* @template E2
|
|
* @type {Chain<E>['chain']}
|
|
* @param {Morphism<E, E2>} _f
|
|
* @returns {this}
|
|
*/
|
|
chainErr(_f) {
|
|
return this;
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Functor<T>['map']}
|
|
* @param {Morphism<T, U>} f
|
|
* @returns {Functor<U>}
|
|
*/
|
|
map(f) {
|
|
return this.chain((v) => ok(f(v)));
|
|
}
|
|
/**
|
|
* @template E2
|
|
* @type {Functor<E>['map']}
|
|
* @this {Result<T, E>}
|
|
* @param {Morphism<E, E2>} _f
|
|
* @returns {Result<T, E2>}
|
|
*/
|
|
mapErr(_f) {
|
|
return (
|
|
/** @type {never} */
|
|
this
|
|
);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Apply<T>['ap']}
|
|
* @param {Apply<Morphism<T, U>>} b
|
|
* @returns {Result<U, E>}
|
|
*/
|
|
ap(b) {
|
|
return (
|
|
/** @type {Result<U, E>} */
|
|
this.chain(
|
|
(v) => (
|
|
/** @type {Chain<U>} */
|
|
b.map((f) => f(v))
|
|
)
|
|
)
|
|
);
|
|
}
|
|
/**
|
|
* @type Alt<T>['alt']
|
|
*/
|
|
alt(_b) {
|
|
return this;
|
|
}
|
|
/**
|
|
* @template U
|
|
* @borrows {Result~map}
|
|
* @param {Morphism<T, U>} f
|
|
*/
|
|
then(f) {
|
|
return this.map(f);
|
|
}
|
|
/**
|
|
* @template R
|
|
* @param {Morphism<E, R>} _f
|
|
* @returns {this}
|
|
*/
|
|
catch(_f) {
|
|
return this;
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {FoldableT<T>['reduce']}
|
|
* @param {(acc: U, value: T) => U} f
|
|
* @param {U} init
|
|
* @returns {U}
|
|
*/
|
|
reduce(f, init) {
|
|
return f(init, this.#value);
|
|
}
|
|
/**
|
|
* @template T2, E2
|
|
* @type {BifunctorT<T, E>['bimap']}
|
|
* @param {Morphism<T, T2>} f
|
|
* @param {Morphism<E, E2>} _g
|
|
* @returns {Result<T2, E2>}
|
|
*/
|
|
bimap(f, _g) {
|
|
return (
|
|
/** @type {Result<T2, E2>} */
|
|
this.map(f)
|
|
);
|
|
}
|
|
toString() {
|
|
return `Ok(${this.#value})`;
|
|
}
|
|
};
|
|
var Err = class _Err extends Interfaces2 {
|
|
/** @type {E} */
|
|
#value;
|
|
/**
|
|
* @param {E} value
|
|
* @constructs {Err<T, E>}
|
|
*/
|
|
constructor(value) {
|
|
super();
|
|
this.#value = value;
|
|
}
|
|
/**
|
|
* @type {SetoidT<T>['equals']}
|
|
* @param {Err<T, E>} other
|
|
* @returns {boolean}
|
|
*/
|
|
equals(other) {
|
|
if (!(other instanceof _Err)) {
|
|
return false;
|
|
}
|
|
const eq = other.chainErr((v) => id(v === this.#value));
|
|
return (
|
|
/** @type {Identity<boolean>} */
|
|
eq.extract()
|
|
);
|
|
}
|
|
/** @returns {this is Ok<T, E>} */
|
|
isOk() {
|
|
return false;
|
|
}
|
|
/** @returns {this is Err<T, E>} */
|
|
isErr() {
|
|
return true;
|
|
}
|
|
/**
|
|
* @type {Chain<T>['chain']}
|
|
* @returns {this}
|
|
*/
|
|
chain(_f) {
|
|
return this;
|
|
}
|
|
/**
|
|
* @template E2
|
|
* @type {Chain<E>['chain']}
|
|
* @param {Morphism<E, Result<T, E2>>} f
|
|
* @returns {Result<T, E2>}
|
|
*/
|
|
chainErr(f) {
|
|
return f(this.#value);
|
|
}
|
|
/**
|
|
* @type {Functor<T>['map']}
|
|
* @returns {this}
|
|
*/
|
|
map(_f) {
|
|
return this;
|
|
}
|
|
/**
|
|
* @template E2
|
|
* @type {Functor<E>['map']}
|
|
* @param {Morphism<E, E2>} f
|
|
* @returns {Result<T, E2>}
|
|
*/
|
|
mapErr(f) {
|
|
return (
|
|
/** @type {Result<T, E2>} */
|
|
this.bimap(id, f)
|
|
);
|
|
}
|
|
/**
|
|
* @type {Functor<T>['map']}
|
|
* @returns {this}
|
|
*/
|
|
then(_f) {
|
|
return this;
|
|
}
|
|
/**
|
|
* @template R
|
|
* @type {Functor<E>['map']}
|
|
* @param {Morphism<E, R>} f
|
|
* @returns {Err<T, R>}
|
|
*/
|
|
catch(f) {
|
|
return new _Err(f(this.#value));
|
|
}
|
|
/**
|
|
* @type Alt<T>['alt']
|
|
*/
|
|
alt(b) {
|
|
return b;
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {FoldableT<T>['reduce']}
|
|
* @param {(acc: U, value: T) => U} _f
|
|
* @param {U} init
|
|
* @returns {U}
|
|
*/
|
|
reduce(_f, init) {
|
|
return init;
|
|
}
|
|
/**
|
|
* @template T2, E2
|
|
* @type {BifunctorT<T, E>['bimap']}
|
|
* @param {Morphism<T, T2>} _f
|
|
* @param {Morphism<E, E2>} g
|
|
* @returns {Result<T2, E2>}
|
|
*/
|
|
bimap(_f, g) {
|
|
return (
|
|
/** @type {Result<T2, E2>} */
|
|
err(g(this.#value))
|
|
);
|
|
}
|
|
toString() {
|
|
return `Err(${this.#value})`;
|
|
}
|
|
};
|
|
var ok = (v) => new Ok(v);
|
|
var err = (e) => new Err(e);
|
|
var TypeRef2 = ok;
|
|
TypeRef2.constructor["of"] = ok;
|
|
TypeRef2.constructor["zero"] = err;
|
|
|
|
// src/algebra/free.js
|
|
var Interfaces3 = Algebra(Monad);
|
|
var Pure = class extends Interfaces3 {
|
|
#value;
|
|
/**
|
|
* @param {T} value
|
|
*/
|
|
constructor(value) {
|
|
super();
|
|
this.#value = value;
|
|
}
|
|
/**
|
|
* @template T
|
|
* @param {T} value
|
|
*/
|
|
static of(value) {
|
|
return liftF(value);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Chain<T>['chain']}
|
|
* @param {Morphism<T, Pure<U>>} f
|
|
* @returns {Pure<U>}
|
|
*/
|
|
chain(f) {
|
|
return f(this.#value);
|
|
}
|
|
/**
|
|
* @type {Functor<T>['map']}
|
|
*/
|
|
map(f) {
|
|
return this.chain((x) => pure(f(x)));
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Apply<T>['ap']}
|
|
* @param {Free<Morphism<T, U>>} b
|
|
* @returns {Free<U>}
|
|
*/
|
|
ap(b) {
|
|
return (
|
|
/** @type {Free<U>} */
|
|
b.chain(
|
|
(f) => (
|
|
/** @type {Chain<U>} */
|
|
this.map(f)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
interpret() {
|
|
return this.#value;
|
|
}
|
|
toString() {
|
|
return `Pure(${this.#value})`;
|
|
}
|
|
};
|
|
var Impure = class extends Interfaces3 {
|
|
#value;
|
|
#next;
|
|
/**
|
|
* @param {T} value
|
|
* @param {(value: T) => Free<any>} next
|
|
*/
|
|
constructor(value, next) {
|
|
super();
|
|
this.#value = value;
|
|
this.#next = next;
|
|
}
|
|
/**
|
|
* @template T
|
|
* @param {T} value
|
|
*/
|
|
static of(value) {
|
|
return liftF(value);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Chain<T>['chain']}
|
|
* @param {Morphism<T, Free<U>>} f
|
|
* @returns {Free<T>}
|
|
*/
|
|
chain(f) {
|
|
return (
|
|
/** @type {Free<T>} */
|
|
impure(
|
|
this.#value,
|
|
(x) => (
|
|
/** @type {Free<U>} */
|
|
this.#next(x).chain(f)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Functor<T>['map']}
|
|
* @param {Morphism<T, U>} f
|
|
* @returns {Free<T>}
|
|
*/
|
|
map(f) {
|
|
return (
|
|
/** @type {Free<T>} */
|
|
impure(
|
|
this.#value,
|
|
(x) => (
|
|
/** @type Free<U>} */
|
|
this.#next(x).map(f)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Apply<T>['ap']}
|
|
* @param {Free<Morphism<T, U>>} b
|
|
* @returns {Free<T>}
|
|
*/
|
|
ap(b) {
|
|
return (
|
|
/** @type {Free<T>} */
|
|
impure(
|
|
this.#value,
|
|
(x) => (
|
|
/** @type {Free<U>} */
|
|
b.chain((f) => (
|
|
/** @type {Free<U>} */
|
|
this.#next(x).map(f)
|
|
))
|
|
)
|
|
)
|
|
);
|
|
}
|
|
interpret() {
|
|
return this.#next(this.#value).interpret();
|
|
}
|
|
toString() {
|
|
return `Impure(${this.#value}, ${this.#next})`;
|
|
}
|
|
};
|
|
var pure = (value) => new Pure(value);
|
|
var impure = (x, f) => new Impure(x, f);
|
|
var liftF = (value) => impure(value, pure);
|
|
var TypeRef3 = Pure;
|
|
TypeRef3.constructor["of"] = Pure;
|
|
|
|
// src/algebra/list.js
|
|
var Interfaces4 = Algebra(Semigroup, Foldable, Monoid, Comonad);
|
|
var Empty = class extends Interfaces4 {
|
|
constructor() {
|
|
super();
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Chain<T>['chain']}
|
|
* @this {Empty<U>}
|
|
* @param {Morphism<T, List<U>>} _f
|
|
* @returns {List<U>}
|
|
*/
|
|
chain(_f) {
|
|
return (
|
|
/** @type {List<U>} */
|
|
this
|
|
);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Functor<T>['map']}
|
|
* @this {Empty<U>}
|
|
* @param {Morphism<T, U>} _f
|
|
* @returns {List<U>}
|
|
*/
|
|
map(_f) {
|
|
return this;
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Apply<T>['ap']}
|
|
* @this {Empty<U>}
|
|
* @param {List<Morphism<T, U>>} _b
|
|
* @returns {List<U>}
|
|
*/
|
|
ap(_b) {
|
|
return (
|
|
/** @type {List<U>} */
|
|
this
|
|
);
|
|
}
|
|
/**
|
|
* @type {SemigroupT<T>['concat']}
|
|
*/
|
|
concat(b) {
|
|
return b;
|
|
}
|
|
/**
|
|
* @type {FoldableT<T>['reduce']}
|
|
*/
|
|
reduce(_f, acc) {
|
|
return acc;
|
|
}
|
|
count() {
|
|
return 0;
|
|
}
|
|
/** @returns {this is Empty<T>} */
|
|
isEmpty() {
|
|
return true;
|
|
}
|
|
toString() {
|
|
return `List(Empty)`;
|
|
}
|
|
};
|
|
var Element = class _Element extends Interfaces4 {
|
|
#head;
|
|
#tail;
|
|
/** @type {List<T>} */
|
|
#cache;
|
|
/**
|
|
* @param {T} head
|
|
* @param {() => List<T>} [tail]
|
|
*/
|
|
constructor(head, tail = List.empty) {
|
|
super();
|
|
this.#head = head;
|
|
this.#tail = tail;
|
|
this.#cache = null;
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Chain<T>['chain']}
|
|
* @this {Element<T>}
|
|
* @param {Morphism<T, List<U>>} f
|
|
* @returns {List<U>}
|
|
*/
|
|
chain(f) {
|
|
return (
|
|
/** @type {List<U>} */
|
|
f(this.#head).concat(
|
|
/** @type {never} */
|
|
this.tail().chain(f)
|
|
)
|
|
);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Functor<T>['map']}
|
|
* @param {Morphism<T, U>} f
|
|
* @returns {List<U>}
|
|
*/
|
|
map(f) {
|
|
return new _Element(
|
|
f(this.#head),
|
|
() => (
|
|
/** @type {List<U>} */
|
|
this.tail().map(f)
|
|
)
|
|
);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Apply<T>['ap']}
|
|
* @this {Element<T>}
|
|
* @param {List<Morphism<T, U>>} b
|
|
* @returns {List<U>}
|
|
*/
|
|
ap(b) {
|
|
if (b.isEmpty()) {
|
|
return List.empty();
|
|
}
|
|
const head = (
|
|
/** @type {List<U>} */
|
|
this.map(b.head())
|
|
);
|
|
const rest = (
|
|
/** @type {List<U>} */
|
|
this.ap(b.tail())
|
|
);
|
|
return (
|
|
/** @type {List<U>} */
|
|
head.concat(rest)
|
|
);
|
|
}
|
|
/**
|
|
* @type {SemigroupT<T>['concat']}
|
|
*/
|
|
concat(b) {
|
|
return new _Element(
|
|
this.#head,
|
|
() => (
|
|
/** @type {List<T>} */
|
|
this.tail().concat(b)
|
|
)
|
|
);
|
|
}
|
|
/**
|
|
* @type {FoldableT<T>['reduce']}
|
|
*/
|
|
reduce(f, acc) {
|
|
return this.tail().reduce(f, f(acc, this.#head));
|
|
}
|
|
head() {
|
|
return this.#head;
|
|
}
|
|
tail() {
|
|
return this.#cache || (this.#cache = this.#tail());
|
|
}
|
|
count() {
|
|
return this.tail().count() + 1;
|
|
}
|
|
/** @returns {this is Empty<T>} */
|
|
isEmpty() {
|
|
return false;
|
|
}
|
|
toArray() {
|
|
return this.reduce(
|
|
reduceArray,
|
|
[]
|
|
);
|
|
}
|
|
toString() {
|
|
return `List(${this.toArray()})`;
|
|
}
|
|
};
|
|
var TypeRef4 = class {
|
|
/**
|
|
* @template T
|
|
* @param {T} value
|
|
* @returns {List<T>}
|
|
*/
|
|
static of(value) {
|
|
return new Element(value);
|
|
}
|
|
/**
|
|
* @template T
|
|
* @param {Iterable<T>} iterable
|
|
* @returns {List<T>}
|
|
*/
|
|
static from(iterable) {
|
|
const iterator = Iterator.from(iterable);
|
|
return List.fromIterator(iterator);
|
|
}
|
|
/**
|
|
* @template T
|
|
* @param {Iterator<T>} iterator
|
|
* @returns {List<T>}
|
|
*/
|
|
static fromIterator(iterator) {
|
|
const next = iterator.next();
|
|
if (next.done) {
|
|
return List.empty();
|
|
} else {
|
|
return new Element(next.value, () => List.fromIterator(iterator));
|
|
}
|
|
}
|
|
/**
|
|
* @template T
|
|
* @param {T} head
|
|
* @param {List<T>} tail
|
|
* @returns {List<T>}
|
|
*/
|
|
static cons(head, tail) {
|
|
return new Element(head, () => tail);
|
|
}
|
|
static empty() {
|
|
return empty;
|
|
}
|
|
};
|
|
var reduceArray = (acc, x) => acc.concat(x);
|
|
var List = TypeRef4;
|
|
var empty = new Empty();
|
|
var list = (value) => List.of(value);
|
|
|
|
// src/algebra/io.js
|
|
var IO = class _IO extends Algebra(Monad) {
|
|
_effect;
|
|
/**
|
|
* @param {T} effect
|
|
*/
|
|
constructor(effect) {
|
|
super();
|
|
this._effect = effect;
|
|
}
|
|
/**
|
|
* @template {Fn} T
|
|
* @param {T} a
|
|
*/
|
|
static of(a) {
|
|
return new _IO(() => a);
|
|
}
|
|
/**
|
|
* @template {Fn} U
|
|
* @type {Chain<T>['chain']}
|
|
* @param {Morphism<T, IO<U>>} f
|
|
* @returns {IO<U>}
|
|
*/
|
|
chain(f) {
|
|
return (
|
|
/** @type {IO<U>} */
|
|
_IO.of(() => f(this.run()).run())
|
|
);
|
|
}
|
|
/**
|
|
* @template {Fn} U
|
|
* @type {Functor<T>['map']}
|
|
* @param {Morphism<T, U>} f
|
|
* @returns {IO<U>}
|
|
*/
|
|
map(f) {
|
|
return (
|
|
/** @type {IO<U>} */
|
|
_IO.of(() => f(this.run()))
|
|
);
|
|
}
|
|
/**
|
|
* @template {Fn} U
|
|
* @type {Apply<T>['ap']}
|
|
* @param {IO<Morphism<T, U>>} other
|
|
* @returns {IO<U>}
|
|
*/
|
|
ap(other) {
|
|
return (
|
|
/** @type {IO<U>} */
|
|
_IO.of(() => other.run()(this.run()))
|
|
);
|
|
}
|
|
run() {
|
|
return this._effect();
|
|
}
|
|
toString() {
|
|
return `IO(${this._effect})`;
|
|
}
|
|
};
|
|
|
|
// node_modules/izuna/src/curry.js
|
|
function curryN(arity, func) {
|
|
return function curried(...args) {
|
|
if (args.length >= arity) {
|
|
return func.apply(this, args);
|
|
} else {
|
|
return function(...args2) {
|
|
return curried.apply(this, args.concat(args2));
|
|
};
|
|
}
|
|
};
|
|
}
|
|
function curry(func) {
|
|
return curryN(func.length, func);
|
|
}
|
|
|
|
// node_modules/izuna/src/list.js
|
|
function isIterable(value) {
|
|
return value[Symbol.iterator] != null;
|
|
}
|
|
function* iter(value) {
|
|
if (isIterable(value)) {
|
|
yield* Iterator.from(value);
|
|
} else {
|
|
yield value;
|
|
}
|
|
}
|
|
var concat = function* (...iterators) {
|
|
for (const iter2 of iterators) {
|
|
for (const item of Iterator.from(iter2)) {
|
|
yield item;
|
|
}
|
|
}
|
|
};
|
|
var prepend = curry(
|
|
/**
|
|
* @template T
|
|
* @param {T} x
|
|
* @param {Iterable<T>} xs
|
|
*/
|
|
(x, xs) => concat([x], xs)
|
|
);
|
|
|
|
// node_modules/izuna/src/function.js
|
|
var id2 = (x) => x;
|
|
var compose = curry(
|
|
/**
|
|
* @template T, U, V
|
|
* @param {Morphism<U, V>} f
|
|
* @param {Morphism<T, U>} g
|
|
* @param {T} x
|
|
* @returns V
|
|
*/
|
|
(f, g, x) => chain(g, chain(f, x))
|
|
);
|
|
var liftA = (a) => Array.isArray(a) ? a : [a];
|
|
var liftF2 = curry((binary, x, y) => binary(x, y));
|
|
var ifElse = curry(
|
|
/**
|
|
* @template T
|
|
* @param {Predicate<T>} pred
|
|
* @param {InferredMorphism<T>} pass
|
|
* @param {InferredMorphism<T>} fail
|
|
* @param {T} x
|
|
*/
|
|
(pred, pass, fail, x) => pred(x) ? pass(x) : fail(x)
|
|
);
|
|
var when = curry(
|
|
/**
|
|
* @template T
|
|
* @param {Predicate<T>} pred
|
|
* @param {InferredMorphism<T>} pass
|
|
* @param {T} x
|
|
*/
|
|
(pred, pass, x) => ifElse(pred, pass, id2, x)
|
|
);
|
|
var unless = curry(
|
|
/**
|
|
* @template T
|
|
* @param {Predicate<T>} pred
|
|
* @param {InferredMorphism<T>} fail
|
|
* @param {T} x
|
|
*/
|
|
(pred, fail, x) => ifElse(pred, id2, fail, x)
|
|
);
|
|
var ap = curry(
|
|
/**
|
|
* @template A, B
|
|
* @template {Morphism<A, B>} Ap
|
|
* @param {Morphism<A, B>} f
|
|
* @param {{ ap: Ap } | Ap} a
|
|
*/
|
|
(f, a) => {
|
|
const fs = liftA(dispatchF("ap", f));
|
|
const args = liftA(a);
|
|
const xs = fs.reduce((acc, f2) => concat(acc, iter(map(f2, args))), []);
|
|
return [...xs];
|
|
}
|
|
);
|
|
var chain = curry(
|
|
function chain2(f, a) {
|
|
}
|
|
);
|
|
var map = curry((f, a) => {
|
|
});
|
|
var reduce = curry((f, acc, xs) => {
|
|
});
|
|
|
|
// node_modules/izuna/src/type.js
|
|
var is = curry(
|
|
/**
|
|
* @template T
|
|
* @param {FunctionConstructor} ctr
|
|
* @param {T} x
|
|
*/
|
|
(ctr, x) => x.constructor === ctr
|
|
);
|
|
var isArray = Array.isArray;
|
|
|
|
// src/algebra/reader.js
|
|
var Reader = class _Reader extends Algebra(Monad) {
|
|
#run;
|
|
/** @param {InferredMorphism<T>} run */
|
|
constructor(run) {
|
|
super();
|
|
this.#run = run;
|
|
}
|
|
/**
|
|
* @template T
|
|
* @type {ApplicativeTypeRef<T, Reader<T>>['of']}
|
|
* @param {T} a
|
|
* @returns {Reader<T>}
|
|
*/
|
|
static of(a) {
|
|
return new _Reader(
|
|
/** @type {InferredMorphism<T>} */
|
|
(_env) => a
|
|
);
|
|
}
|
|
/** @template T */
|
|
static ask() {
|
|
return new _Reader(
|
|
/** @type {InferredMorphism<T>} */
|
|
id2
|
|
);
|
|
}
|
|
/**
|
|
* @type {Functor<T>['map']}
|
|
* @param {InferredMorphism<T>} f
|
|
* @returns {Reader<T>}
|
|
*/
|
|
map(f) {
|
|
return (
|
|
/** @type {Reader<any>} */
|
|
this.chain((value) => _Reader.of(f(value)))
|
|
);
|
|
}
|
|
/**
|
|
* @type {Chain<T>['chain']}
|
|
* @param {InferredMorphism<T>} f
|
|
* @returns {Reader<T>}
|
|
*/
|
|
chain(f) {
|
|
return new _Reader((env) => {
|
|
const result = this.#run(env);
|
|
const next = f(result);
|
|
return next.run(env);
|
|
});
|
|
}
|
|
/**
|
|
* @template U
|
|
* @type {Apply<T>['ap']}
|
|
* @param {Reader<Morphism<T, U>>} b
|
|
* @returns {Reader<U>}
|
|
*/
|
|
ap(b) {
|
|
return (
|
|
/** @type {Reader<U>} */
|
|
b.chain(
|
|
(f) => (
|
|
/** @type {Reader<U>} */
|
|
this.map(f)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
/**
|
|
* @param {InferredMorphism<T>} f
|
|
* @returns {Reader<T>}
|
|
*/
|
|
local(f) {
|
|
return new _Reader(
|
|
/** @type {InferredMorphism<T>} */
|
|
(env) => this.#run(f(env))
|
|
);
|
|
}
|
|
/**
|
|
* @template U
|
|
* @param {T} env
|
|
* @returns {U}
|
|
*/
|
|
run(env) {
|
|
return this.#run(env);
|
|
}
|
|
};
|
|
})();
|