change type ref pattern; update type signatures

This commit is contained in:
Rowan 2025-04-12 02:28:18 -05:00
parent 19f02031b0
commit cafa3a8fa7
7 changed files with 199 additions and 72 deletions

View file

@ -64,7 +64,7 @@ export class Pure extends Algebra(Monad, Traversable) {
* @returns {Applicative<Free<U>>}
*/
traverse(_A, f) {
return f(this.#value).map(pure)
return /** @type {Applicative<Free<U>>} */ (f(this.#value).map(pure))
}
run() {
@ -157,9 +157,9 @@ export class Impure extends Algebra(Monad, Foldable, Traversable) {
const rest = next.traverse(A, f)
return /** @type {Applicative<Free<U>>} */ (rest.ap(
fb.map(b => next => impure(b, () =>
/** @type {Free<U>} */(next)
))
/** @type {Apply<Morphism<TraversableT<U>, U>>} */(fb.map(b => next => impure(b, () =>
/** @type {Free<U>} */(next)
)))
))
}
}

View file

@ -1,6 +1,6 @@
import { Algebra, Comonad, Monad } from './interfaces.js'
/** @import { Apply, Morphism } from './types.js' */
/** @import { Apply, Functor, Morphism } from './types.js' */
/** @template T */
export class Identity extends Algebra(Monad, Comonad) {
@ -25,10 +25,11 @@ export class Identity extends Algebra(Monad, Comonad) {
/**
* @template U
* @type {Functor<T>['map']}
* @param {Morphism<T, U>} f
* @returns {Identity<U>}
*/
map(f) {
console.log(this.toString(), f.toString())
return id(f(this.#value))
}
@ -66,5 +67,9 @@ export class Identity extends Algebra(Monad, Comonad) {
}
}
/**
* @template T
* @param {T} value
*/
export const id = value => new Identity(value)

View file

@ -1,6 +1,6 @@
import { Algebra, Monad } from './interfaces.js'
/** @import { Fn, InferredMorphism, Morphism } from './types.js' */
/** @import { Apply, Chain, Fn, Functor, InferredMorphism, Morphism } from './types.js' */
/** @template {Fn} T */
export class IO extends Algebra(Monad) {
@ -23,26 +23,33 @@ export class IO extends Algebra(Monad) {
}
/**
* @param {InferredMorphism<T>} f
* @template {Fn} U
* @type {Chain<T>['chain']}
* @param {Morphism<T, IO<U>>} f
* @returns {IO<U>}
*/
chain(f) {
return IO.of(() => f(this.run()).run())
}
/**
* @param {InferredMorphism<T>} f
*/
map(f) {
return IO.of(() => f(this.run()))
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<T>}
* @returns {IO<U>}
*/
ap(other) {
return /** @type {IO<T>} */ (IO.of((() => other.run()(this.run()))))
return /** @type {IO<U>} */ (IO.of((() => other.run()(this.run()))))
}
run() {

View file

@ -1,8 +1,9 @@
import { Algebra, Foldable, Monad, Setoid } from './interfaces.js'
import { id, Identity } from './identity.js'
import { Algebra, Alternative, Foldable, Monad, Setoid } from './interfaces.js'
/** @import { Morphism } from './types.js' */
/** @import { Alt, Apply, Chain, Foldable as FoldableT, Functor, Morphism, Setoid as SetoidT } from './types.js' */
const Interfaces = Algebra(Setoid, Monad, Foldable)
const Interfaces = Algebra(Setoid, Alternative, Monad, Foldable)
/**
* @template T
@ -22,39 +23,53 @@ export class Some extends Interfaces {
}
/**
* @param {Option<T>} other
* @type {SetoidT<T>['equals']}
* @param {Some<T>} other
*/
equals(other) {
return other instanceof Some &&
other.chain(v => v === this.#value)
}
ap(b) {
return b.chain(f => this.map(f))
if (other instanceof Some) { return false }
const eq = /** @type {Some<T>} */ (other).chain(v => id(v === this.#value))
return /** @type {Identity<boolean>} */ (eq).extract()
}
/**
* @template R
* @param {Morphism<T, R>} f
* @returns {R}
* @template U
* @type {Apply<T>['ap']}
* @param {Some<Morphism<T, U>>} b
* @returns {Some<U>}
*/
ap(b) {
return /** @type {Some<U>} */ (b.chain(f =>
/** @type {Some<U>} */(this.map(f))
))
}
/**
* @type {Alt<T>['alt']}
*/
alt(b) {
return this
}
/**
* @type {Chain<T>['chain']}
*/
chain(f) {
return f(this.#value)
}
/**
* @template R
* @param {Morphism<T, R>} f
* @returns {Some<R>}
* @template U
* @type {Functor<T>['map']}
* @param {Morphism<T, U>} f
* @returns {Some<U>}
*/
map(f) {
return Some.of(this.chain(f))
return /** @type {Some<U>} */ (this.chain(v => some(f(v))))
}
/**
* @template R
* @param {Morphism<T, R>} f
* @returns {Some<R>}
* @type {Functor<T>['map']}
*/
then(f) {
return this.map(f)
@ -62,6 +77,7 @@ export class Some extends Interfaces {
/**
* @template U
* @type {FoldableT<T>['reduce']}
* @param {(acc: U, value: T) => U} f
* @param {U} init
* @returns {U}
@ -74,29 +90,42 @@ export class Some extends Interfaces {
/** @template T */
export class None extends Interfaces {
/**
* @param {Option<T>} other
* @type {SetoidT<T>['equals']}
*/
equals(other) {
return other === none
}
/**
* @type {Apply<T>['ap']}
* @returns {this}
*/
ap(_b) {
return this
}
/**
* @template R
* @param {Morphism<T, R>} _f
* @returns {None}
* @type {Alt<T>['alt']}
*/
alt(b) {
return b
}
/**
* @template U
* @type {Chain<T>['chain']}
* @param {Morphism<T, U>} _f
* @returns {this}
*/
chain(_f) {
return this
}
/**
* @template R
* @param {Morphism<T, R>} _f
* @returns {None}
* @template U
* @type {Functor<T>['map']}
* @param {Morphism<T, U>} _f
* @returns {this}
*/
map(_f) {
return this
@ -104,6 +133,7 @@ export class None extends Interfaces {
/**
* @template R
* @type {Functor<T>['map']}
* @param {Morphism<T, R>} _f
* @returns {None}
*/
@ -113,6 +143,7 @@ export class None extends Interfaces {
/**
* @template U
* @type {FoldableT<T>['reduce']}
* @param {(acc: U, value: T) => U} _f
* @param {U} init
* @returns {U}

View file

@ -1,7 +1,7 @@
import { id } from '../../vendor/izuna/src/index.js'
import { Algebra, Monad } from './interfaces.js'
/** @import { InferredMorphism, Morphism } from './types.js' */
/** @import { Apply, Chain, Functor, InferredMorphism, Morphism } from './types.js' */
/**
* @template T
@ -34,14 +34,17 @@ export class Reader extends Algebra(Monad) {
}
/**
* @param {InferredMorphism<T>} f
* @returns {Reader<T>}
* @template U
* @type {Functor<T>['map']}
* @param {Morphism<T, U>} f
* @returns {Reader<U>}
*/
map(f) {
return new Reader(/** @type {InferredMorphism<T>} */(env => f(this.#run(env))))
return new Reader(env => f(this.#run(env)))
}
/**
* @type {Chain<T>['chain']}
* @param {InferredMorphism<T>} f
* @returns {Reader<T>}
*/
@ -50,14 +53,13 @@ export class Reader extends Algebra(Monad) {
}
/**
* @template R
* @param {Reader<(v: T) => R>} other
* @returns {Reader<R>}
* @template U
* @type {Apply<T>['ap']}
* @param {Reader<Morphism<T, U>>} other
* @returns {Reader<U>}
*/
ap(other) {
return new Reader(
// FIXME: type errors
// @ts-ignore
env => other.run(env)(this.run(env))
)
}
@ -71,9 +73,9 @@ export class Reader extends Algebra(Monad) {
}
/**
* @template R
* @template U
* @param {T} env
* @returns {R}
* @returns {U}
*/
run(env) {
return this.#run(env)

View file

@ -1,9 +1,9 @@
import { id, Identity } from './identity.js'
import { Algebra, Bifunctor, Foldable, Monad, Setoid } from './interfaces.js'
import { Algebra, Alternative, Bifunctor, Foldable, Monad, Setoid } from './interfaces.js'
/** @import { Apply, Chain, Functor, Bifunctor as BifunctorT, Foldable as FoldableT, Morphism, Setoid as SetoidT } from './types.js' */
/** @import { Alt, Apply, Chain, Functor, Bifunctor as BifunctorT, Foldable as FoldableT, Morphism, Setoid as SetoidT } from './types.js' */
const Interfaces = Algebra(Setoid, Monad, Foldable, Bifunctor)
const Interfaces = Algebra(Setoid, Alternative, Monad, Foldable, Bifunctor)
/**
* @template T, E
@ -51,6 +51,16 @@ export class Ok extends Interfaces {
return f(this.#value)
}
/**
* @template E2
* @type {Chain<E>['chain']}
* @param {Morphism<E, E2>} _f
* @returns {this}
*/
chainErr(_f) {
return this
}
/**
* @template U
* @type {Functor<T>['map']}
@ -61,6 +71,17 @@ export class Ok extends Interfaces {
return this.chain(v => ok(f(v)))
}
/**
* @template E2
* @type {Functor<E>['map']}
* @this {Result<T, E>}
* @param {Morphism<E, E2>} _f
* @returns {Result<T, E2>}
*/
mapErr(_f) {
return /** @type {never} */ (this)
}
/**
* @template U
* @type {Apply<T>['ap']}
@ -73,6 +94,13 @@ export class Ok extends Interfaces {
))
}
/**
* @type Alt<T>['alt']
*/
alt(_b) {
return this
}
/**
* @template U
* @borrows {Result~map}
@ -101,6 +129,17 @@ export class Ok extends Interfaces {
reduce(f, init) {
return f(init, this.#value)
}
/**
* @template T2, E2
* @type {BifunctorT<T, E>['bimap']}
* @param {Morphism<T, T2>} f
* @param {Morphism<E, E2>} _g
* @returns {Result<T2, E2>}
*/
bimap(f, _g) {
return /** @type {Result<T2, E2>} */ (this.map(f))
}
}
/**
@ -110,7 +149,6 @@ export class Err extends Interfaces {
/** @type {E} */
#value
/**
* @param {E} value
* @constructs {Err<T, E>}
@ -120,7 +158,6 @@ export class Err extends Interfaces {
this.#value = value
}
/**
* @type {SetoidT<T>['equals']}
* @param {Err<T, E>} other
@ -128,7 +165,7 @@ export class Err extends Interfaces {
*/
equals(other) {
if (!(other instanceof Err)) { return false }
const eq = other.catch(v => (id(v === this.#value)))
const eq = other.chainErr(v => id(v === this.#value))
return /** @type {Identity<boolean>} */ (eq).extract()
}
@ -139,8 +176,7 @@ export class Err extends Interfaces {
isErr() { return true }
/**
* @template R
* @param {Morphism<T, R>} _f
* @type {Chain<T>['chain']}
* @returns {this}
*/
chain(_f) {
@ -148,8 +184,17 @@ export class Err extends Interfaces {
}
/**
* @template R
* @param {Morphism<T, R>} _f
* @template E2
* @type {Chain<E>['chain']}
* @param {Morphism<E, Result<T, E2>>} f
* @returns {Result<T, E2>}
*/
chainErr(f) {
return f(this.#value)
}
/**
* @type {Functor<T>['map']}
* @returns {this}
*/
map(_f) {
@ -157,8 +202,17 @@ export class Err extends Interfaces {
}
/**
* @template R
* @param {Morphism<T, R>} _f
* @template E2
* @type {Functor<E>['map']}
* @param {Morphism<E, E2>} f
* @returns {Result<T, E2>}
*/
mapErr(f) {
return /** @type {Result<T, E2>} */ (this.bimap(id, f))
}
/**
* @type {Functor<T>['map']}
* @returns {this}
*/
then(_f) {
@ -167,6 +221,7 @@ export class Err extends Interfaces {
/**
* @template R
* @type {Functor<E>['map']}
* @param {Morphism<E, R>} f
* @returns {Err<T, R>}
*/
@ -174,8 +229,16 @@ export class Err extends Interfaces {
return new Err(f(this.#value))
}
/**
* @type Alt<T>['alt']
*/
alt(b) {
return b
}
/**
* @template U
* @type {FoldableT<T>['reduce']}
* @param {(acc: U, value: T) => U} _f
* @param {U} init
* @returns {U}
@ -183,6 +246,17 @@ export class Err extends Interfaces {
reduce(_f, init) {
return init
}
/**
* @template T2, E2
* @type {BifunctorT<T, E>['bimap']}
* @param {Morphism<T, T2>} _f
* @param {Morphism<E, E2>} g
* @returns {Result<T2, E2>}
*/
bimap(_f, g) {
return /** @type {Result<T2, E2>} */ (err(g(this.#value)))
}
}
/**

View file

@ -108,10 +108,10 @@ export default {}
/**
* @template T
* @typedef {{
ap: <U>(b: Applicative<Morphism<U, T>>) => Applicative<T>,
map: <U>(f: Morphism<T, U>) => Applicative<U>
* }} Applicative
* @typedef {
Functor<T> &
Apply<T>
* } Applicative
*/
/**
@ -210,5 +210,13 @@ export default {}
* } Comonad<T>
*/
/**
* @template A, X
* @typedef {
Functor<A> &
{ bimap: <B, Y>(f: Morphism<A, B>, g: Morphism<X, Y>) => Bifunctor<B, Y> }
* } Bifunctor
*/
/** @typedef {(...args: any[]) => any} Fn */