189 lines
2.8 KiB
JavaScript
189 lines
2.8 KiB
JavaScript
import { Algebra, Foldable, Functor, Monad, Setoid } from './interfaces.js'
|
|
|
|
/** @import { Morphism } from './types.js' */
|
|
|
|
/**
|
|
* @template T, E
|
|
*/
|
|
export class Ok extends Algebra(Setoid, Monad, Foldable) {
|
|
/** @type {T} */
|
|
#value
|
|
|
|
/**
|
|
* @param {T} value
|
|
* @constructs {Ok<T, E>}
|
|
*/
|
|
constructor(value) {
|
|
super()
|
|
|
|
this.#value = value
|
|
}
|
|
|
|
/**
|
|
* @param {Ok<T, E>} other
|
|
*/
|
|
equals(other) {
|
|
return other instanceof Ok &&
|
|
other.chain(v => v === this.#value)
|
|
}
|
|
|
|
/** @returns {this is Ok<T, E>} */
|
|
isOk() { return true }
|
|
|
|
/** @returns {this is Err<T, E>} */
|
|
isErr() { return false }
|
|
|
|
/**
|
|
* @template R
|
|
* @param {Morphism<T, R>} f
|
|
* @this {Ok<T, E>}
|
|
* @returns {R}
|
|
*/
|
|
chain(f) {
|
|
return f(this.#value)
|
|
}
|
|
|
|
/**
|
|
* @template R
|
|
* @param {Morphism<T, R>} f
|
|
* @this {Ok<T, E>}
|
|
* @returns {Ok<R, E>}
|
|
*/
|
|
map(f) {
|
|
return Result.of(this.chain(f))
|
|
}
|
|
|
|
/**
|
|
* @template R
|
|
* @param {Morphism<T, R>} f
|
|
* @this {Ok<T, E>}
|
|
* @returns {Ok<R, E>}
|
|
*/
|
|
then(f) {
|
|
return this.map(f)
|
|
}
|
|
|
|
/**
|
|
* @template R
|
|
* @param {Morphism<E, R>} _f
|
|
* @returns {this}
|
|
*/
|
|
catch(_f) {
|
|
return this
|
|
}
|
|
|
|
/**
|
|
* @template U
|
|
* @param {(acc: U, value: T) => U} f
|
|
* @param {U} init
|
|
* @returns {U}
|
|
*/
|
|
reduce(f, init) {
|
|
return f(init, this.#value)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @template T, E
|
|
*/
|
|
export class Err extends Algebra(Setoid, Functor, Monad) {
|
|
/** @type {E} */
|
|
#value
|
|
|
|
|
|
/**
|
|
* @param {E} value
|
|
* @constructs {Err<T, E>}
|
|
*/
|
|
constructor(value) {
|
|
super()
|
|
this.#value = value
|
|
}
|
|
|
|
equals(other) {
|
|
return other instanceof Err &&
|
|
other.chain(v => v === this.#value)
|
|
}
|
|
|
|
/** @returns {this is Ok<T, E>} */
|
|
isOk() { return false }
|
|
|
|
/** @returns {this is Err<T, E>} */
|
|
isErr() { return true }
|
|
|
|
/**
|
|
* @template R
|
|
* @param {Morphism<T, R>} _f
|
|
* @returns {this}
|
|
*/
|
|
chain(_f) {
|
|
return this
|
|
}
|
|
|
|
/**
|
|
* @template R
|
|
* @param {Morphism<T, R>} _f
|
|
* @returns {this}
|
|
*/
|
|
map(_f) {
|
|
return this
|
|
}
|
|
|
|
/**
|
|
* @template R
|
|
* @param {Morphism<T, R>} _f
|
|
* @returns {this}
|
|
*/
|
|
then(_f) {
|
|
return this
|
|
}
|
|
|
|
/**
|
|
* @template R
|
|
* @param {Morphism<E, R>} f
|
|
* @returns {Err<T, R>}
|
|
*/
|
|
catch(f) {
|
|
return new Err(f(this.#value))
|
|
}
|
|
|
|
/**
|
|
* @template U
|
|
* @param {(acc: U, value: T) => U} _f
|
|
* @param {U} init
|
|
* @returns {U}
|
|
*/
|
|
reduce(_f, init) {
|
|
return init
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @template T, E
|
|
* @type {Ok<T, E> | Err<T, E>} Result
|
|
*/
|
|
export class Result {
|
|
/**
|
|
* @template T
|
|
* @param {T} value
|
|
* @returns {Ok}
|
|
*/
|
|
static of(value) {
|
|
return new Ok(value)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @template T, E
|
|
* @param {T} v
|
|
* @returns {Ok<T, E>}
|
|
*/
|
|
export const ok = v => new Ok(v)
|
|
|
|
/**
|
|
* @template T, E
|
|
* @param {E} e
|
|
* @returns {Err<T, E>}
|
|
*/
|
|
export const err = e => new Err(e)
|
|
|