wip cons list
This commit is contained in:
parent
e213666051
commit
0336213ca9
5 changed files with 140 additions and 72 deletions
|
@ -2,7 +2,7 @@
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "es2020",
|
"module": "es2020",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"lib": ["es2022", "dom"],
|
"lib": ["esnext", "dom"],
|
||||||
"checkJs": true,
|
"checkJs": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"/*": ["./*"]
|
"/*": ["./*"]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { curry } from '../curry.js'
|
import { curry } from '../curry.js'
|
||||||
import { Free, Suspend, pure } from './free.js'
|
import { Free, Suspend, suspend, pure } from './free.js'
|
||||||
|
|
||||||
/** @import {InferredMorphism, Morphism, ChainConstructor} from './types.js' */
|
/** @import {InferredMorphism, Morphism, ChainConstructor} from './types.js' */
|
||||||
|
|
||||||
|
@ -35,9 +35,9 @@ export const kleisliCompose = curry(
|
||||||
/**
|
/**
|
||||||
* @template T
|
* @template T
|
||||||
* @param {T} x
|
* @param {T} x
|
||||||
* @returns {Free<T>}
|
* @returns {Suspend<T>}
|
||||||
*/
|
*/
|
||||||
export const liftF = x => new Suspend(
|
export const liftF = x => suspend(
|
||||||
x,
|
x,
|
||||||
/** @type {InferredMorphism<T>} */(pure)
|
/** @type {InferredMorphism<T>} */(pure)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import { liftF } from './fn.js'
|
import { liftF } from './fn.js'
|
||||||
import { Algebra, Comonad, EitherOf, Functor, Monad } from './index.js'
|
import { Algebra, BaseSet, Comonad, Monad } from './index.js'
|
||||||
|
|
||||||
/** @import { InferredMorphism, Morphism } from './types.js' */
|
/** @import { InferredMorphism, Morphism } from './types.js' */
|
||||||
|
|
||||||
/** @template T */
|
/**
|
||||||
export class Suspend extends Algebra(Functor, Monad) {
|
* @template T
|
||||||
#value
|
* @extends BaseSet
|
||||||
|
* @mixes Monad
|
||||||
|
*/
|
||||||
|
export class Suspend extends Algebra(Monad) {
|
||||||
|
_value
|
||||||
#fn
|
#fn
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,7 +18,7 @@ export class Suspend extends Algebra(Functor, Monad) {
|
||||||
*/
|
*/
|
||||||
constructor(value, fn) {
|
constructor(value, fn) {
|
||||||
super()
|
super()
|
||||||
this.#value = value
|
this._value = value
|
||||||
this.#fn = fn
|
this.#fn = fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +34,7 @@ export class Suspend extends Algebra(Functor, Monad) {
|
||||||
* @returns {Suspend<T>}
|
* @returns {Suspend<T>}
|
||||||
*/
|
*/
|
||||||
chain(f) {
|
chain(f) {
|
||||||
return new Suspend(this.#value, x => this.#fn(x).chain(f))
|
return new Suspend(this._value, x => this.#fn(x).chain(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,7 +43,7 @@ export class Suspend extends Algebra(Functor, Monad) {
|
||||||
* @returns {Suspend<T>}
|
* @returns {Suspend<T>}
|
||||||
*/
|
*/
|
||||||
map(g) {
|
map(g) {
|
||||||
return new Suspend(this.#value, x => this.#fn(x).map(g))
|
return new Suspend(this._value, x => this.#fn(x).map(g))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,19 +55,23 @@ export class Suspend extends Algebra(Functor, Monad) {
|
||||||
return this.map(g)
|
return this.map(g)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
step() {
|
||||||
|
return this.#fn(this._value)
|
||||||
|
}
|
||||||
|
|
||||||
run() {
|
run() {
|
||||||
return this.#fn(this.#value)
|
return this.step().run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @template T */
|
/** @template T */
|
||||||
export class Pure extends Algebra(Functor, Monad, Comonad) {
|
export class Pure extends Algebra(Monad, Comonad) {
|
||||||
#value
|
_value
|
||||||
|
|
||||||
/** @param {T} value */
|
/** @param {T} value */
|
||||||
constructor(value) {
|
constructor(value) {
|
||||||
super()
|
super()
|
||||||
this.#value = value
|
this._value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {this is Pure<T>} */
|
/** @returns {this is Pure<T>} */
|
||||||
|
@ -78,7 +86,7 @@ export class Pure extends Algebra(Functor, Monad, Comonad) {
|
||||||
* @returns {Pure<U>}
|
* @returns {Pure<U>}
|
||||||
*/
|
*/
|
||||||
chain(f) {
|
chain(f) {
|
||||||
return f(this.#value)
|
return f(this._value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,11 +108,15 @@ export class Pure extends Algebra(Functor, Monad, Comonad) {
|
||||||
}
|
}
|
||||||
|
|
||||||
extract() {
|
extract() {
|
||||||
return this.#value
|
return this._value
|
||||||
|
}
|
||||||
|
|
||||||
|
step() {
|
||||||
|
return this._value
|
||||||
}
|
}
|
||||||
|
|
||||||
run() {
|
run() {
|
||||||
return this.#value
|
return this._value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -215,13 +215,7 @@ class Interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @template T */
|
/** @template T */
|
||||||
class BaseSet {
|
export class BaseSet {
|
||||||
_value
|
|
||||||
|
|
||||||
/** @param {T} value */
|
|
||||||
constructor(value) {
|
|
||||||
this._value = value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -250,13 +244,19 @@ export const apply = (methodName, f, obj) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Function} base
|
||||||
|
* @returns {(...algebras: Interface[]) => FunctionConstructor}
|
||||||
|
*/
|
||||||
|
export const AlgebraWithBase = base => (...algebras) => {
|
||||||
|
return mix(base).with(...algebras.map(x => x.intoWrapper()))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {...Interface} algebras
|
* @param {...Interface} algebras
|
||||||
* @returns {FunctionConstructor}
|
* @returns {FunctionConstructor}
|
||||||
*/
|
*/
|
||||||
export const Algebra = (...algebras) => {
|
export const Algebra = AlgebraWithBase(BaseSet)
|
||||||
return mix(BaseSet).with(...algebras.map(x => x.intoWrapper()))
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Setoid = new Interface('Setoid')
|
export const Setoid = new Interface('Setoid')
|
||||||
.specifies('equals')
|
.specifies('equals')
|
||||||
|
@ -331,7 +331,7 @@ export const Chain = new Interface('Chain')
|
||||||
Method.from('chain')
|
Method.from('chain')
|
||||||
.implementation(function(f) {
|
.implementation(function(f) {
|
||||||
return f(this._value)
|
return f(this._value)
|
||||||
}))
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
export const ChainRef = new Interface('ChainRec')
|
export const ChainRef = new Interface('ChainRec')
|
||||||
|
|
|
@ -1,54 +1,110 @@
|
||||||
import { liftF } from './fn.js'
|
import { liftF } from './fn.js'
|
||||||
import { Free } from './free.js'
|
import { Pure, Suspend } from './free.js'
|
||||||
import { Algebra, Foldable, Functor, Monad } from './index.js'
|
import { AlgebraWithBase, Comonad, Foldable } from './index.js'
|
||||||
import { none as None } from './option.js'
|
|
||||||
|
|
||||||
/** @template T */
|
/** @import { InferredMorphism } from './types.js' */
|
||||||
export class List extends Algebra(Functor, Monad, Foldable) {
|
|
||||||
/** @type {Free<T> | None<T>} */
|
|
||||||
_head
|
|
||||||
|
|
||||||
/** @type {List<T>} */
|
const Nil = Symbol('Nil')
|
||||||
_tail
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {T | None} [head]
|
* @template T
|
||||||
* @param {List<T>} [tail=List]
|
* @extends {Pure<T>}
|
||||||
*/
|
*/
|
||||||
constructor(head = None, tail = List.of(None)) {
|
class ListPure extends AlgebraWithBase(Pure)(Foldable) {
|
||||||
super()
|
head() {
|
||||||
this._head = head
|
return this.head
|
||||||
this._tail = tail
|
}
|
||||||
|
|
||||||
|
tail() {
|
||||||
|
return Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template U
|
||||||
|
* @param {(acc: U, value: T) => U} f
|
||||||
|
* @param {U} init
|
||||||
|
* @returns {U}
|
||||||
|
*/
|
||||||
|
reduce(f, init) {
|
||||||
|
return f(init, this._value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T
|
||||||
|
* @extends {Suspend<T>}
|
||||||
|
*/
|
||||||
|
class ListSuspend extends AlgebraWithBase(Suspend)(Foldable, Comonad) {
|
||||||
|
/**
|
||||||
|
* @param {IteratorObject<T>} iter
|
||||||
|
*/
|
||||||
|
constructor(iter) {
|
||||||
|
const next = iter.next()
|
||||||
|
const value = /** @type {T} */ (next.value)
|
||||||
|
|
||||||
|
const fn = /** @type {InferredMorphism<T>} */ (next.done ? List.empty : () => new ListSuspend(iter))
|
||||||
|
super(value, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
head() {
|
||||||
|
return this._value
|
||||||
|
}
|
||||||
|
|
||||||
|
tail() {
|
||||||
|
return this.step()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template U
|
||||||
|
* @param {(acc: U, value: T) => U} f
|
||||||
|
* @param {U} init
|
||||||
|
* @returns {U}
|
||||||
|
*/
|
||||||
|
reduce(f, init) {
|
||||||
|
const acc = f(init, this._value)
|
||||||
|
return this.tail().reduce(f, acc)
|
||||||
|
}
|
||||||
|
|
||||||
|
extract() {
|
||||||
|
return this.reduce((acc, value) => acc.concat(value), [])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template T
|
* @template T
|
||||||
* @param {T} value
|
* @type {ListPure<T> | ListSuspend<T>} List
|
||||||
* @returns {List<T>}
|
|
||||||
*/
|
*/
|
||||||
prepend(value) {
|
export class List {
|
||||||
return new List(value, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template T
|
* @template {Iterable<T>} T
|
||||||
* @param {T} value
|
* @param {T} value
|
||||||
* @returns {List<T>}
|
* @returns {ListSuspend<T>}
|
||||||
*/
|
*/
|
||||||
static of(value) {
|
static of(value) {
|
||||||
return new List(value)
|
// @ts-ignore
|
||||||
|
return new ListSuspend(liftF(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template T
|
* @template T
|
||||||
* @param {Iterable<T>} iterable
|
* @param {Iterable<T>} iterator
|
||||||
* @returns {List<T>}
|
* @returns {ListSuspend<T>}
|
||||||
*/
|
*/
|
||||||
static from(iterable) {
|
static from(iterator) {
|
||||||
Array.from(iterable).reduceRight((list, value))
|
return new ListSuspend(Iterator.from(iterator))
|
||||||
|
}
|
||||||
|
|
||||||
|
static empty() {
|
||||||
|
return Empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const list = liftF(1)
|
const Empty = new ListPure(Nil)
|
||||||
console.log(list.map(_ => 2).map(_ => 3).chain(x => x).run())
|
|
||||||
|
|
||||||
|
const a = Array.from({ length: 100 }).map((_, i) => i)
|
||||||
|
|
||||||
|
const wawa = List.from(a)
|
||||||
|
console.log(wawa.reduce((acc, value) => acc.concat(value), []))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue