Add product and sum types

This commit is contained in:
Joeri Exelmans 2025-03-17 17:54:42 +01:00
parent 6023efc295
commit 574651ccb7
18 changed files with 209 additions and 157 deletions

62
type_registry.js Normal file
View file

@ -0,0 +1,62 @@
// This module ensures that we never accidentally create a Symbol for the same type twice.
// Maybe we shouldn't use Symbols for types, but we also cannot use primitive values for types because they may accidentally overlap with 'real' values (that are not types)
// We also cannot use objects for types because similar to Symbols, objects are only equal to themselves if we use them as Map keys.
import { DefaultMap } from "./util.js";
// Global store of function types:
const fnTypes = new DefaultMap(() => new Map());
export const fnType = ({in: inType, out: outType}) => {
const m2 = fnTypes.getdefault(inType, true);
if (m2.has(outType)) {
return m2.get(outType);
}
else {
const fnType = {in: inType, out: outType};
m2.set(outType, fnType);
return fnType;
}
};
// Global store of list types:
const listTypes = new Map();
export function getListType(elementType) {
if (listTypes.has(elementType)) {
// only generate each list type once
// this would not be necessary if we could define our own equality and hash functions on objects in JavaScript.
return listTypes.get(elementType);
}
else {
const type = Symbol('ListOf:' + elementType.toString());
listTypes.set(elementType, type);
return type;
}
}
// Global store of product types:
const productTypes = new DefaultMap(() => new Map());
export const prodType = (leftType, rightType) => {
const m2 = productTypes.getdefault(leftType, true);
if (m2.has(rightType)) {
return m2.get(rightType);
}
else {
const pt = Symbol(`${leftType.toString()} × ${rightType.toString()}`);
m2.set(rightType, pt);
return pt;
}
}
// Global store of sum types:
const sumTypes = new DefaultMap(() => new Map());
export const sumType = (leftType, rightType) => {
const m2 = sumTypes.getdefault(leftType, true);
if (m2.has(rightType)) {
return m2.get(rightType);
}
else {
const st = Symbol(`${leftType.toString()} + ${rightType.toString()}`);
m2.set(rightType, st);
return st;
}
}