wip method typing
This commit is contained in:
parent
619f24c7dc
commit
19f02031b0
3 changed files with 63 additions and 69 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue