simplify 'enum'

This commit is contained in:
Joeri Exelmans 2025-06-03 10:42:36 +02:00
parent 366b1ec4e0
commit aee8d5b5e1
6 changed files with 113 additions and 59 deletions

View file

@ -1,6 +1,4 @@
import { capitalizeFirstLetter } from "../util/util.js";
import { newProduct as newProduct, getLeft } from "./product.js";
import { newLeft, newRight, match } from "./sum.js";
const eatParameters = (numParams, result) => {
if (numParams === 0) {
@ -9,29 +7,38 @@ const eatParameters = (numParams, result) => {
else return () => eatParameters(numParams-1, result);
}
export const makeMatchFn = variants => {
if (variants.length === 0) {
throw new Error("Bottom!");
export const makeMatchFn = variantNames => {
if (variantNames.length === 0) {
return _ => {
throw new Error("Bottom!");
};
}
const [_, ...remainingVariants] = variants;
return sum => handler => {
return match(sum)
(leftValue => eatParameters(remainingVariants.length, handler(leftValue)))
(rightValue => makeMatchFn(remainingVariants)(rightValue));
return enumm => {
return matchFn(enumm, variantNames);
}
};
const matchFn = (enumm, variantNames) => {
const [variantName, ...remaining] = variantNames;
return handler => {
if (enumm.variant === variantName) {
return eatParameters(
remaining.length,
handler(enumm.value));
}
else {
return matchFn(enumm, remaining);
}
};
};
export const makeConstructors = variants => {
if (variants.length === 0) {
return [];
export const makeConstructors = variantNames => {
if (new Set(variantNames).size !== variantNames.length) {
throw new Error("precondition failed: non-unique variant names");
}
const [variant, ...remainingVariants] = variants;
const name = getLeft(variant);
const ctorName = `new${capitalizeFirstLetter(name)}`;
const constructor = { [ctorName]: val => newLeft(val) }[ctorName];
return [
constructor,
...makeConstructors(remainingVariants).map(ctor =>
({[ctor.name]: val => newRight(ctor(val))}[ctor.name])),
];
return variantNames.map(variantName => {
const ctorName = `new${capitalizeFirstLetter(variantName)}`;
const ctor = { [ctorName]: value => ({variant: variantName, value}) }[ctorName];
return ctor;
})
};