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['chain']} * @param {Morphism>} f * @returns {IO} */ chain(f) { return /** @type {IO} */ (IO.of(() => f(this.run()).run())) } /** * @template {Fn} U * @type {Functor['map']} * @param {Morphism} f * @returns {IO} */ map(f) { return /** @type {IO} */ (IO.of(() => f(this.run()))) } /** * @template {Fn} U * @type {Apply['ap']} * @param {IO>} other * @returns {IO} */ ap(other) { return /** @type {IO} */ (IO.of((() => other.run()(this.run())))) } run() { return this._effect() } toString() { return `IO(${this._effect})` } }