From f20cf6841abfb590ec91fdb1db9c35366a37f188 Mon Sep 17 00:00:00 2001 From: rowan Date: Thu, 17 Apr 2025 12:52:29 -0500 Subject: [PATCH] add dispatch methods --- .gitignore | 2 ++ package-lock.json | 22 ++++++++++++++++++++++ package.json | 7 +++++-- src/fantasy-land.js | 7 +++++-- src/function.js | 34 ++++++++++++++++++++-------------- test/index.js | 7 +++++++ test/units/index.js | 16 ++++++++++++++++ 7 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 .gitignore create mode 100644 package-lock.json create mode 100755 test/index.js create mode 100644 test/units/index.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d570088 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c40f9c2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,22 @@ +{ + "name": "izuna", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "izuna", + "version": "1.0.0", + "license": "GPL-3.0-or-later", + "devDependencies": { + "folktest": "git+https://git.kitsu.cafe/rowan/folktest.git" + } + }, + "node_modules/folktest": { + "version": "1.0.0", + "resolved": "git+https://git.kitsu.cafe/rowan/folktest.git#708d44f1215be33fcceba426029f44b4f963dbe5", + "dev": true, + "license": "GPL-3.0-or-later" + } + } +} diff --git a/package.json b/package.json index 079ed35..4e6f020 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,12 @@ "type": "module", "main": "src/index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "./test/index.js" }, "keywords": [], "license": "GPL-3.0-or-later", - "description": "" + "description": "", + "devDependencies": { + "folktest": "git+https://git.kitsu.cafe/rowan/folktest.git" + } } diff --git a/src/fantasy-land.js b/src/fantasy-land.js index aa00a55..b319825 100644 --- a/src/fantasy-land.js +++ b/src/fantasy-land.js @@ -1,6 +1,8 @@ +import { isArray, isFn } from './type.js' +import { last } from './list.js' /** * @param {PropertyKey[]} methods - * @param {Fn} f + * @param {import('./types.js').Fn} f */ export function dispatch(methods, f) { return function() { @@ -12,7 +14,8 @@ export function dispatch(methods, f) { const obj = last(args) if (!isArray(obj)) { - for (let i = 0; i < obj.length; i++) { + const len = methods.length + for (let i = 0; i < len; i++) { const fn = obj[methods[i]] if (isFn(fn)) { return fn.apply(obj, args.slice(0, -1)) diff --git a/src/function.js b/src/function.js index 0be2312..ac74879 100644 --- a/src/function.js +++ b/src/function.js @@ -1,5 +1,6 @@ import { curry, curryN } from './curry.js' -import { concat, iter } from './list.js' +import { dispatch } from './fantasy-land.js' +import { concat as iconcat, iter } from './list.js' /** @import { Fn, Morphism, InferredMorphism, Predicate } from './types.js' */ @@ -16,7 +17,11 @@ export const id = x => x */ export const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x) -export const compose = curry( +export const concat = curry(dispatch(['fantasy-land/concat', 'concat'], + (b, a) => iconcat(iter(a), iter(b)) +)) + +export const compose = curry(dispatch(['fantasy-land/compose', 'compose'], /** * @template T, U, V * @param {Morphism} f @@ -25,7 +30,7 @@ export const compose = curry( * @returns V */ (f, g, x) => chain(g, chain(f, x)) -) +)) /** * @template T @@ -107,7 +112,7 @@ export const unless = curry( * @typedef {(f: F, a: A) => B} StaticMorphism */ -export const ap = curry( +export const ap = curry(dispatch(['fantasy-land/ap', 'ap'], /** * @template A, B * @template {Morphism} Ap @@ -115,7 +120,7 @@ export const ap = curry( * @param {{ ap: Ap } | Ap} a */ (f, a) => { - const fs = liftA(dispatchF('ap', f)) + const fs = liftA(f) const args = liftA(a) const xs = fs.reduce((acc, f) => ( @@ -123,16 +128,17 @@ export const ap = curry( ), []) return [...xs] - }) + })) -export const chain = curry( - function chain(f, a) { - }) +export const chain = curry(dispatch(['fantasy-land/chain', 'chain'], + (f, a) => a.map(f) +)) -export const map = curry((f, a) => { -}) +export const map = curry(dispatch(['fantasy-land/map', 'map'], + (f, a) => a.map(f) +)) -export const reduce = curry((f, acc, xs) => { - -}) +export const reduce = curry(dispatch(['fantasy-land/reduce', 'reduce'], + (f, acc, xs) => xs.reduce(f, acc) +)) diff --git a/test/index.js b/test/index.js new file mode 100755 index 0000000..d9b03db --- /dev/null +++ b/test/index.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +import { TerminalRunner } from 'folktest' +import * as Tests from './units/index.js' + +console.log(TerminalRunner(Tests).toString()) + diff --git a/test/units/index.js b/test/units/index.js new file mode 100644 index 0000000..47103c2 --- /dev/null +++ b/test/units/index.js @@ -0,0 +1,16 @@ +import { it, assert } from 'folktest' +import { dispatch } from '../../src/fantasy-land.js' + +const obj = { + 'test': a => console.log('test', a) +} + +export const Tests = [ + it('whatever', () => { + const f = dispatch(['fantasy-land/test', 'test'], (f, a) => { + console.log(f, a) + }) + console.log(f(1, obj)) + }) +] +