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": {
|
||||
"module": "es2020",
|
||||
"target": "es6",
|
||||
"lib": ["es2022", "dom"],
|
||||
"lib": ["esnext", "dom"],
|
||||
"checkJs": true,
|
||||
"paths": {
|
||||
"/*": ["./*"]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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' */
|
||||
|
||||
|
@ -35,9 +35,9 @@ export const kleisliCompose = curry(
|
|||
/**
|
||||
* @template T
|
||||
* @param {T} x
|
||||
* @returns {Free<T>}
|
||||
* @returns {Suspend<T>}
|
||||
*/
|
||||
export const liftF = x => new Suspend(
|
||||
export const liftF = x => suspend(
|
||||
x,
|
||||
/** @type {InferredMorphism<T>} */(pure)
|
||||
)
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
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' */
|
||||
|
||||
/** @template T */
|
||||
export class Suspend extends Algebra(Functor, Monad) {
|
||||
#value
|
||||
/**
|
||||
* @template T
|
||||
* @extends BaseSet
|
||||
* @mixes Monad
|
||||
*/
|
||||
export class Suspend extends Algebra(Monad) {
|
||||
_value
|
||||
#fn
|
||||
|
||||
/**
|
||||
|
@ -14,7 +18,7 @@ export class Suspend extends Algebra(Functor, Monad) {
|
|||
*/
|
||||
constructor(value, fn) {
|
||||
super()
|
||||
this.#value = value
|
||||
this._value = value
|
||||
this.#fn = fn
|
||||
}
|
||||
|
||||
|
@ -30,7 +34,7 @@ export class Suspend extends Algebra(Functor, Monad) {
|
|||
* @returns {Suspend<T>}
|
||||
*/
|
||||
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>}
|
||||
*/
|
||||
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)
|
||||
}
|
||||
|
||||
step() {
|
||||
return this.#fn(this._value)
|
||||
}
|
||||
|
||||
run() {
|
||||
return this.#fn(this.#value)
|
||||
return this.step().run()
|
||||
}
|
||||
}
|
||||
|
||||
/** @template T */
|
||||
export class Pure extends Algebra(Functor, Monad, Comonad) {
|
||||
#value
|
||||
export class Pure extends Algebra(Monad, Comonad) {
|
||||
_value
|
||||
|
||||
/** @param {T} value */
|
||||
constructor(value) {
|
||||
super()
|
||||
this.#value = value
|
||||
this._value = value
|
||||
}
|
||||
|
||||
/** @returns {this is Pure<T>} */
|
||||
|
@ -78,7 +86,7 @@ export class Pure extends Algebra(Functor, Monad, Comonad) {
|
|||
* @returns {Pure<U>}
|
||||
*/
|
||||
chain(f) {
|
||||
return f(this.#value)
|
||||
return f(this._value)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,11 +108,15 @@ export class Pure extends Algebra(Functor, Monad, Comonad) {
|
|||
}
|
||||
|
||||
extract() {
|
||||
return this.#value
|
||||
return this._value
|
||||
}
|
||||
|
||||
step() {
|
||||
return this._value
|
||||
}
|
||||
|
||||
run() {
|
||||
return this.#value
|
||||
return this._value
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -214,14 +214,8 @@ class Interface {
|
|||
}
|
||||
}
|
||||
|
||||
/** @template T*/
|
||||
class BaseSet {
|
||||
_value
|
||||
|
||||
/** @param {T} value */
|
||||
constructor(value) {
|
||||
this._value = value
|
||||
}
|
||||
/** @template T */
|
||||
export class BaseSet {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
* @returns {FunctionConstructor}
|
||||
*/
|
||||
export const Algebra = (...algebras) => {
|
||||
return mix(BaseSet).with(...algebras.map(x => x.intoWrapper()))
|
||||
}
|
||||
export const Algebra = AlgebraWithBase(BaseSet)
|
||||
|
||||
export const Setoid = new Interface('Setoid')
|
||||
.specifies('equals')
|
||||
|
@ -331,7 +331,7 @@ export const Chain = new Interface('Chain')
|
|||
Method.from('chain')
|
||||
.implementation(function(f) {
|
||||
return f(this._value)
|
||||
}))
|
||||
})
|
||||
)
|
||||
|
||||
export const ChainRef = new Interface('ChainRec')
|
||||
|
|
|
@ -1,54 +1,110 @@
|
|||
import { liftF } from './fn.js'
|
||||
import { Free } from './free.js'
|
||||
import { Algebra, Foldable, Functor, Monad } from './index.js'
|
||||
import { none as None } from './option.js'
|
||||
import { Pure, Suspend } from './free.js'
|
||||
import { AlgebraWithBase, Comonad, Foldable } from './index.js'
|
||||
|
||||
/** @template T */
|
||||
export class List extends Algebra(Functor, Monad, Foldable) {
|
||||
/** @type {Free<T> | None<T>} */
|
||||
_head
|
||||
/** @import { InferredMorphism } from './types.js' */
|
||||
|
||||
/** @type {List<T>} */
|
||||
_tail
|
||||
const Nil = Symbol('Nil')
|
||||
|
||||
/**
|
||||
* @param {T | None} [head]
|
||||
* @param {List<T>} [tail=List]
|
||||
*/
|
||||
constructor(head = None, tail = List.of(None)) {
|
||||
super()
|
||||
this._head = head
|
||||
this._tail = tail
|
||||
/**
|
||||
* @template T
|
||||
* @extends {Pure<T>}
|
||||
*/
|
||||
class ListPure extends AlgebraWithBase(Pure)(Foldable) {
|
||||
head() {
|
||||
return this.head
|
||||
}
|
||||
|
||||
tail() {
|
||||
return Empty
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} value
|
||||
* @returns {List<T>}
|
||||
* @template U
|
||||
* @param {(acc: U, value: T) => U} f
|
||||
* @param {U} init
|
||||
* @returns {U}
|
||||
*/
|
||||
prepend(value) {
|
||||
return new List(value, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} value
|
||||
* @returns {List<T>}
|
||||
*/
|
||||
static of(value) {
|
||||
return new List(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {Iterable<T>} iterable
|
||||
* @returns {List<T>}
|
||||
*/
|
||||
static from(iterable) {
|
||||
Array.from(iterable).reduceRight((list, value))
|
||||
reduce(f, init) {
|
||||
return f(init, this._value)
|
||||
}
|
||||
}
|
||||
|
||||
const list = liftF(1)
|
||||
console.log(list.map(_ => 2).map(_ => 3).chain(x => x).run())
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @type {ListPure<T> | ListSuspend<T>} List
|
||||
*/
|
||||
export class List {
|
||||
/**
|
||||
* @template {Iterable<T>} T
|
||||
* @param {T} value
|
||||
* @returns {ListSuspend<T>}
|
||||
*/
|
||||
static of(value) {
|
||||
// @ts-ignore
|
||||
return new ListSuspend(liftF(value))
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {Iterable<T>} iterator
|
||||
* @returns {ListSuspend<T>}
|
||||
*/
|
||||
static from(iterator) {
|
||||
return new ListSuspend(Iterator.from(iterator))
|
||||
}
|
||||
|
||||
static empty() {
|
||||
return Empty
|
||||
}
|
||||
}
|
||||
|
||||
const Empty = new ListPure(Nil)
|
||||
|
||||
|
||||
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