wip method typing

This commit is contained in:
Rowan 2025-04-11 18:16:01 -05:00
parent 619f24c7dc
commit 19f02031b0
3 changed files with 63 additions and 69 deletions

View file

@ -2,10 +2,7 @@ import { Algebra, Foldable, Monad, Traversable } from './interfaces.js'
import { curry } from '../..//vendor/izuna/src/index.js' import { curry } from '../..//vendor/izuna/src/index.js'
import { Reducer } from './utilities.js' import { Reducer } from './utilities.js'
/** @import { Applicative, ApplicativeTypeRef, Apply, Chain, Comonad, Foldable as FoldableT, Functor, Monad as MonadT, Morphism, Traversable as TraversableT } from './types.js' */ /** @import { Applicative, ApplicativeTypeRef, Apply, Chain, Foldable as FoldableT, Functor, Morphism, Traversable as TraversableT } from './types.js' */
/** @import { InferredMorphism } from './types.js' */
const kleisli = curry((f, g, x) => f(x).chain(g)) const kleisli = curry((f, g, x) => f(x).chain(g))
@ -13,7 +10,6 @@ const kleisli = curry((f, g, x) => f(x).chain(g))
* @template T * @template T
* @typedef {Pure<T> | Impure<T>} Free * @typedef {Pure<T> | Impure<T>} Free
*/ */
const Free = {}
/** @template T */ /** @template T */
export class Pure extends Algebra(Monad, Traversable) { export class Pure extends Algebra(Monad, Traversable) {
@ -188,16 +184,15 @@ const pure = x => new Pure(x)
*/ */
const impure = (x, f) => new Impure(x, f) const impure = (x, f) => new Impure(x, f)
/** /**
* @template T * @template T
* @param {T} x * @param {T} x
* @returns Impure<T> * @returns Impure<T>
*/ */
export const liftF = x => impure(x, pure) export const liftF = x => impure(x, pure)
import { id, Identity } from './identity.js'
import { Option, some } from './option.js'
const a = liftF(1).chain(() => liftF(2)).reduce((acc, x) => acc + x, 0) const TypeRef = () => { }
console.log(a) TypeRef.constructor.of = pure
export const Free = TypeRef

View file

@ -1,23 +1,16 @@
import { Algebra, Foldable, Monad, Monoid, Setoid } from './interfaces.js' import { Algebra, Foldable, Monad, Setoid } from './interfaces.js'
/** @import { Morphism } from './types.js' */ /** @import { Morphism } from './types.js' */
const Interfaces = Algebra(Setoid, Monad, Foldable)
/** /**
* @template T * @template T
* @type {Some<T> | None<T>} Option * @typedef {Some<T> | None<T>} Option
*/ */
export class Option extends Algebra(Setoid, Monad, Foldable) {
/**
* @template T
* @param {T} value
*/
static of(value) {
return Some.of(value)
}
}
/** @template T */ /** @template T */
export class Some extends Option { export class Some extends Interfaces {
/** @type {T} */ /** @type {T} */
#value #value
@ -28,15 +21,6 @@ export class Some extends Option {
this.#value = value this.#value = value
} }
/**
* @template T
* @param {T} value
* @returns {Some<T>}
*/
static of(value) {
return new Some(value)
}
/** /**
* @param {Option<T>} other * @param {Option<T>} other
*/ */
@ -88,7 +72,7 @@ export class Some extends Option {
} }
/** @template T */ /** @template T */
export class None extends Option { export class None extends Interfaces {
/** /**
* @param {Option<T>} other * @param {Option<T>} other
*/ */
@ -136,10 +120,6 @@ export class None extends Option {
reduce(_f, init) { reduce(_f, init) {
return init return init
} }
empty() {
return Option.empty()
}
} }
/** /**
@ -149,3 +129,9 @@ export class None extends Option {
export const some = value => new Some(value) export const some = value => new Some(value)
export const none = new None() export const none = new None()
const TypeRef = some
TypeRef.constructor['of'] = some
TypeRef.constructor['zero'] = none
export const Option = TypeRef

View file

@ -1,26 +1,19 @@
import { Algebra, Foldable, Monad, Setoid } from './interfaces.js' import { id, Identity } from './identity.js'
import { Algebra, Bifunctor, Foldable, Monad, Setoid } from './interfaces.js'
/** @import { Morphism } from './types.js' */ /** @import { Apply, Chain, Functor, Bifunctor as BifunctorT, Foldable as FoldableT, Morphism, Setoid as SetoidT } from './types.js' */
const Interfaces = Algebra(Setoid, Monad, Foldable, Bifunctor)
/** /**
* @template T, E * @template T, E
* @type {Ok<T, E> | Err<T, E>} Result * @typedef {Ok<T, E> | Err<T, E>} Result
*/ */
export class Result extends Algebra(Setoid, Monad, Foldable) {
/**
* @template T
* @param {T} value
* @returns {Ok}
*/
static of(value) {
return new Ok(value)
}
}
/** /**
* @template T, E * @template T, E
*/ */
export class Ok extends Result { export class Ok extends Interfaces {
/** @type {T} */ /** @type {T} */
#value #value
@ -35,11 +28,14 @@ export class Ok extends Result {
} }
/** /**
* @type {SetoidT<T>['equals']}
* @param {Result<T, E>} other * @param {Result<T, E>} other
* @returns {boolean}
*/ */
equals(other) { equals(other) {
return other instanceof Ok && if (!(other instanceof Ok)) { return false }
other.chain(v => v === this.#value) const eq = other.chain(v => (id(v === this.#value)))
return /** @type {Identity<boolean>} */ (eq).extract()
} }
/** @returns {this is Ok<T, E>} */ /** @returns {this is Ok<T, E>} */
@ -49,30 +45,38 @@ export class Ok extends Result {
isErr() { return false } isErr() { return false }
/** /**
* @template R * @type {Chain<T>['chain']}
* @param {Morphism<T, R>} f
* @this {Ok<T, E>}
* @returns {R}
*/ */
chain(f) { chain(f) {
return f(this.#value) return f(this.#value)
} }
/** /**
* @template R * @template U
* @param {Morphism<T, R>} f * @type {Functor<T>['map']}
* @this {Ok<T, E>} * @param {Morphism<T, U>} f
* @returns {Ok<R, E>} * @returns {Functor<U>}
*/ */
map(f) { map(f) {
return Result.of(this.chain(f)) return this.chain(v => ok(f(v)))
} }
/** /**
* @template R * @template U
* @param {Morphism<T, R>} f * @type {Apply<T>['ap']}
* @this {Ok<T, E>} * @param {Apply<Morphism<T, U>>} b
* @returns {Ok<R, E>} * @returns {Result<U, E>}
*/
ap(b) {
return /** @type {Result<U, E>} */ (this.chain(v =>
/** @type {Chain<U>} */(b.map(f => f(v)))
))
}
/**
* @template U
* @borrows {Result~map}
* @param {Morphism<T, U>} f
*/ */
then(f) { then(f) {
return this.map(f) return this.map(f)
@ -89,6 +93,7 @@ export class Ok extends Result {
/** /**
* @template U * @template U
* @type {FoldableT<T>['reduce']}
* @param {(acc: U, value: T) => U} f * @param {(acc: U, value: T) => U} f
* @param {U} init * @param {U} init
* @returns {U} * @returns {U}
@ -101,7 +106,7 @@ export class Ok extends Result {
/** /**
* @template T, E * @template T, E
*/ */
export class Err extends Result { export class Err extends Interfaces {
/** @type {E} */ /** @type {E} */
#value #value
@ -115,12 +120,16 @@ export class Err extends Result {
this.#value = value this.#value = value
} }
/** /**
* @param {Result<T, E>} other * @type {SetoidT<T>['equals']}
* @param {Err<T, E>} other
* @returns {boolean}
*/ */
equals(other) { equals(other) {
return other instanceof Err && if (!(other instanceof Err)) { return false }
other.chain(v => v === this.#value) const eq = other.catch(v => (id(v === this.#value)))
return /** @type {Identity<boolean>} */ (eq).extract()
} }
/** @returns {this is Ok<T, E>} */ /** @returns {this is Ok<T, E>} */
@ -190,3 +199,7 @@ export const ok = v => new Ok(v)
*/ */
export const err = e => new Err(e) export const err = e => new Err(e)
const TypeRef = ok
TypeRef.constructor['of'] = ok
TypeRef.constructor['zero'] = err