kojima/src/algebra/io.js
2025-04-13 04:45:12 -05:00

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})`
}
}