import { chain, constant, Self, Value } from './common.js' /** @import { Morphism } from './common.js' */ /** * @template T, E * @typedef {Ok | Err} Result */ /** * @template T * @typedef Ok * @property {typeof isOk} isOk * @property {typeof isErr} isErr * @property {typeof chain} chain * @property {typeof map} map * @property {typeof alt} alt * @property {typeof fold} fold */ /** * @template T * @typedef Err * @property {typeof isOk} isOk * @property {typeof isErr} isErr * @property {typeof chain} chain * @property {typeof map} map * @property {typeof alt} alt * @property {typeof fold} fold */ /** * @template T, U, E * @this {Result} * @param {Morphism} fn * @returns {Result} */ function map(fn) { return this[Self](this.chain(fn)) } /** * @template T, U, E * @this {Result} * @param {Morphism>} fn * @param {U} acc * @return {U} */ function fold(fn, acc) { const result = this.map(fn) return result.isOk() ? result[Value] : acc } /** * @template T, E * @this {Result} * @param {Result} other * @returns {Result} */ function alt(other) { return this.isOk() ? this : other } /** * @template T, E * @this {Result} * @returns {this is Ok} */ function isOk() { return this[Self] === Ok } /** * @template T, E * @this {Result} * @returns {this is Err} */ function isErr() { return this[Self] === Err } /** * @template T * @param {?T} value * @returns {Ok} */ export const Ok = value => Object.freeze({ [Self]: Ok, [Value]: value, isOk, isErr, chain, map, alt, fold }) /** * @template T * @param {T?} value * @returns {Err} */ export const Err = value => Object.freeze({ [Self]: Err, [Value]: value, chain: constant, map: constant, alt, isOk, isErr, fold }) /** * @template T, E * @param {T} value * @returns {Result} */ export const Result = value => Ok(value) Result.of = Result Result.zero = () => Err(undefined)