move functions to own library
This commit is contained in:
parent
f79a2ca462
commit
96cc50ad34
6 changed files with 40 additions and 180 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "vendor/izuna"]
|
||||
path = vendor/izuna
|
||||
url = git@git.kitsu.cafe:rowan/izuna.git
|
|
@ -1,67 +0,0 @@
|
|||
import { curry } from '../curry.js'
|
||||
import { concat } from '../iter.js'
|
||||
import { Impure, pure, impure } from './free.js'
|
||||
|
||||
/** @import {InferredMorphism, Morphism, ChainConstructor} from './types.js' */
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} x
|
||||
* @returns {x}
|
||||
*/
|
||||
export const id = x => x
|
||||
|
||||
export const compose = curry(
|
||||
/**
|
||||
* @template T, U, V
|
||||
* @param {Morphism<U, V>} f
|
||||
* @param {Morphism<T, U>} g
|
||||
* @param {T} x
|
||||
* @returns V
|
||||
*/
|
||||
(f, g, x) => f(g(x))
|
||||
)
|
||||
|
||||
export const kleisliCompose = curry(
|
||||
/**
|
||||
* @template {ChainConstructor<T>} M, T, U
|
||||
* @param {M} f
|
||||
* @param {Morphism<T, U>} g
|
||||
* @param {T} x
|
||||
* @returns U
|
||||
*/
|
||||
(f, g, x) => f(x).chain(g)
|
||||
)
|
||||
|
||||
export const lift = (...args) => args
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} x
|
||||
* @returns {Impure<T>}
|
||||
*/
|
||||
export const liftF = x => impure(
|
||||
x,
|
||||
/** @type {InferredMorphism<T>} */(pure)
|
||||
)
|
||||
|
||||
/**
|
||||
* @param {number} a
|
||||
* @param {number} b
|
||||
* @returns {number}
|
||||
*/
|
||||
export const add = (a, b) => a + b
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T} x
|
||||
* @returns {() => T}
|
||||
*/
|
||||
export const thunk = x => () => x
|
||||
|
||||
export const prepend = (x, xs) => concat([x], xs)
|
||||
|
||||
export const type = x => typeof x
|
||||
export const is = (ctr, x) => x.constructor === ctr
|
||||
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import { Option } from './option.js'
|
||||
import { thunk } from './fn.js'
|
||||
import { id, map, ap, prepend, reduce, thunk } from './fn.js'
|
||||
/** @import { Morphism } from './types.js' */
|
||||
|
||||
|
||||
|
@ -50,8 +49,8 @@ export class Pure {
|
|||
return b.map(this.#value)
|
||||
}
|
||||
|
||||
traverse(f, A) {
|
||||
return A.of(this.map(f))
|
||||
traverse(f, of) {
|
||||
return of(this.map(f))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,9 +130,9 @@ export class Impure {
|
|||
)
|
||||
}
|
||||
|
||||
traverse(f, A) {
|
||||
return A.of(liftF(
|
||||
this.#next().traverse(f, A)
|
||||
traverse(f, of) {
|
||||
return of(liftF(
|
||||
this.#next().traverse(f, of)
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -144,9 +143,36 @@ export class Impure {
|
|||
* @returns {B}
|
||||
*/
|
||||
reduce(f, acc) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const sequence = (of, iter) => {
|
||||
console.log(ap(of([]), 1))
|
||||
return reduce((acc, x) => {
|
||||
ap(acc, map(prepend, x))
|
||||
}, of([]), iter)
|
||||
}
|
||||
|
||||
|
||||
class Reducer {
|
||||
constructor(v) {
|
||||
this.value = v
|
||||
}
|
||||
|
||||
static of(v) {
|
||||
return new Reducer(v)
|
||||
}
|
||||
|
||||
ap(other) {
|
||||
console.log(this, other)
|
||||
return this.value(other.value)
|
||||
}
|
||||
}
|
||||
|
||||
const r = Reducer.of
|
||||
console.log(sequence(r, [r(1), r(2), r(3)]))
|
||||
|
||||
/**
|
||||
* @template A
|
||||
* @param {A} x
|
||||
|
@ -161,3 +187,6 @@ export const pure = x => new Pure(x)
|
|||
export const impure = f => new Impure(f)
|
||||
export const liftF = effect => impure(thunk(effect))
|
||||
|
||||
const xs = liftF(pure(1)).map(thunk(2)).map(thunk(3))
|
||||
console.log(xs.traverse(id, id))
|
||||
|
||||
|
|
72
src/curry.js
72
src/curry.js
|
@ -1,72 +0,0 @@
|
|||
/**
|
||||
* @template {(...args: any[]) => any} F
|
||||
* @typedef {F extends ((...args: infer A) => any) ? A : never} Params
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {any[]} T
|
||||
* @typedef {T extends [any, ...any[]] ? T[0] : never} Head
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {any[]} T
|
||||
* @typedef {((...t: T) => any) extends ((_: any, ...tail: infer TT) => any) ? TT : []} Tail
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {any[]} T
|
||||
* @typedef {T extends ([] | [any]) ? false : true} HasTail
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {any[]} T
|
||||
* @typedef {{ 0: Last<Tail<T>>; 1: Head<T> }[HasTail<T> extends true ? 0 : 1]} Last
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {any[]} T
|
||||
* @typedef {T['length']} Length
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template E
|
||||
* @template {any[]} T
|
||||
* @typedef {((head: E, ...args: T) => any) extends ((...args: infer U) => any) ? U : T} Prepend
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {number} N
|
||||
* @template {any[]} T
|
||||
* @template {any[]} [I = []]
|
||||
* @typedef {{ 0: Drop<N, Tail<T>, Prepend<any, I>>; 1: T }[Length<I> extends N ? 1 : 0]} Drop
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template X, Y
|
||||
* @typedef {X extends Y ? X : Y} Cast
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {any[]} P, R
|
||||
* @typedef {<T extends any[]>(...args: Cast<T, Partial<P>>) => Drop<Length<T>, P> extends [any, ...any[]] ? Curried<Cast<Drop<Length<T>, P>, any[]>, R> : R} Curried
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {any[]} P, R
|
||||
* @param {(...args: P) => R} func
|
||||
* @returns {Curried<P, R>}
|
||||
*/
|
||||
export function curry(func) {
|
||||
return function curried(...args) {
|
||||
if (args.length >= func.length) {
|
||||
return func.apply(this, args)
|
||||
} else {
|
||||
/** @type {Curried<P, R>} */
|
||||
return function(...args2) {
|
||||
return curried.apply(this, args.concat(args2))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
34
src/iter.js
34
src/iter.js
|
@ -1,34 +0,0 @@
|
|||
/**
|
||||
* @template T
|
||||
* @param {T | Iterable<T> | Iterator<T>} value
|
||||
* @returns {value is Iterable<T>}
|
||||
*/
|
||||
export function isIterable(value) {
|
||||
return value[Symbol.iterator] != null
|
||||
}
|
||||
/**
|
||||
* @template T
|
||||
* @param {T | Iterable<T> | Iterator<T>} value
|
||||
* @yields {T}
|
||||
*/
|
||||
export function* iter(value) {
|
||||
if (isIterable(value)) {
|
||||
yield* Iterator.from(value)
|
||||
} else {
|
||||
yield value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {...(Iterable<T> | Iterator<T>)} iterators
|
||||
* @yields {T}
|
||||
*/
|
||||
export const concat = function*(...iterators) {
|
||||
for (const iter of iterators) {
|
||||
for (const item of Iterator.from(iter)) {
|
||||
yield item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
vendor/izuna
vendored
Submodule
1
vendor/izuna
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit d9daed0d0977f7b79462fb204a5d89b827dcac1b
|
Loading…
Add table
Reference in a new issue