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 { 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 { InferredMorphism } from './types.js' */
|
||||
/** @import { Applicative, ApplicativeTypeRef, Apply, Chain, Foldable as FoldableT, Functor, Morphism, Traversable as TraversableT } from './types.js' */
|
||||
|
||||
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
|
||||
* @typedef {Pure<T> | Impure<T>} Free
|
||||
*/
|
||||
const Free = {}
|
||||
|
||||
/** @template T */
|
||||
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)
|
||||
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} x
|
||||
* @returns Impure<T>
|
||||
*/
|
||||
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)
|
||||
console.log(a)
|
||||
const TypeRef = () => { }
|
||||
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' */
|
||||
|
||||
const Interfaces = Algebra(Setoid, Monad, Foldable)
|
||||
|
||||
/**
|
||||
* @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 */
|
||||
export class Some extends Option {
|
||||
export class Some extends Interfaces {
|
||||
/** @type {T} */
|
||||
#value
|
||||
|
||||
|
@ -28,15 +21,6 @@ export class Some extends Option {
|
|||
this.#value = value
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} value
|
||||
* @returns {Some<T>}
|
||||
*/
|
||||
static of(value) {
|
||||
return new Some(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Option<T>} other
|
||||
*/
|
||||
|
@ -88,7 +72,7 @@ export class Some extends Option {
|
|||
}
|
||||
|
||||
/** @template T */
|
||||
export class None extends Option {
|
||||
export class None extends Interfaces {
|
||||
/**
|
||||
* @param {Option<T>} other
|
||||
*/
|
||||
|
@ -136,10 +120,6 @@ export class None extends Option {
|
|||
reduce(_f, 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 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
|
||||
* @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
|
||||
*/
|
||||
export class Ok extends Result {
|
||||
export class Ok extends Interfaces {
|
||||
/** @type {T} */
|
||||
#value
|
||||
|
||||
|
@ -35,11 +28,14 @@ export class Ok extends Result {
|
|||
}
|
||||
|
||||
/**
|
||||
* @type {SetoidT<T>['equals']}
|
||||
* @param {Result<T, E>} other
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(other) {
|
||||
return other instanceof Ok &&
|
||||
other.chain(v => v === this.#value)
|
||||
if (!(other instanceof Ok)) { return false }
|
||||
const eq = other.chain(v => (id(v === this.#value)))
|
||||
return /** @type {Identity<boolean>} */ (eq).extract()
|
||||
}
|
||||
|
||||
/** @returns {this is Ok<T, E>} */
|
||||
|
@ -49,30 +45,38 @@ export class Ok extends Result {
|
|||
isErr() { return false }
|
||||
|
||||
/**
|
||||
* @template R
|
||||
* @param {Morphism<T, R>} f
|
||||
* @this {Ok<T, E>}
|
||||
* @returns {R}
|
||||
* @type {Chain<T>['chain']}
|
||||
*/
|
||||
chain(f) {
|
||||
return f(this.#value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @template R
|
||||
* @param {Morphism<T, R>} f
|
||||
* @this {Ok<T, E>}
|
||||
* @returns {Ok<R, E>}
|
||||
* @template U
|
||||
* @type {Functor<T>['map']}
|
||||
* @param {Morphism<T, U>} f
|
||||
* @returns {Functor<U>}
|
||||
*/
|
||||
map(f) {
|
||||
return Result.of(this.chain(f))
|
||||
return this.chain(v => ok(f(v)))
|
||||
}
|
||||
|
||||
/**
|
||||
* @template R
|
||||
* @param {Morphism<T, R>} f
|
||||
* @this {Ok<T, E>}
|
||||
* @returns {Ok<R, E>}
|
||||
* @template U
|
||||
* @type {Apply<T>['ap']}
|
||||
* @param {Apply<Morphism<T, U>>} b
|
||||
* @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) {
|
||||
return this.map(f)
|
||||
|
@ -89,6 +93,7 @@ export class Ok extends Result {
|
|||
|
||||
/**
|
||||
* @template U
|
||||
* @type {FoldableT<T>['reduce']}
|
||||
* @param {(acc: U, value: T) => U} f
|
||||
* @param {U} init
|
||||
* @returns {U}
|
||||
|
@ -101,7 +106,7 @@ export class Ok extends Result {
|
|||
/**
|
||||
* @template T, E
|
||||
*/
|
||||
export class Err extends Result {
|
||||
export class Err extends Interfaces {
|
||||
/** @type {E} */
|
||||
#value
|
||||
|
||||
|
@ -115,12 +120,16 @@ export class Err extends Result {
|
|||
this.#value = value
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {Result<T, E>} other
|
||||
* @type {SetoidT<T>['equals']}
|
||||
* @param {Err<T, E>} other
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(other) {
|
||||
return other instanceof Err &&
|
||||
other.chain(v => v === this.#value)
|
||||
if (!(other instanceof Err)) { return false }
|
||||
const eq = other.catch(v => (id(v === this.#value)))
|
||||
return /** @type {Identity<boolean>} */ (eq).extract()
|
||||
}
|
||||
|
||||
/** @returns {this is Ok<T, E>} */
|
||||
|
@ -190,3 +199,7 @@ export const ok = v => new Ok(v)
|
|||
*/
|
||||
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