63 lines
1.1 KiB
JavaScript
63 lines
1.1 KiB
JavaScript
import { Algebra, Monad } from './interfaces.js'
|
|
|
|
/** @import { Apply, Chain, Fn, Functor, Morphism } from './types.js' */
|
|
|
|
/** @template {Fn} T */
|
|
export 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})`
|
|
}
|
|
}
|
|
|