import { Unit } from "../primitives/types.js"; import { unit } from "../primitives/unit.js"; import { constructorProduct, getLeft, getRight } from "./product.js"; import { fnType, prodType } from "./types.js"; function capitalizeFirstLetter(val) { return String(val).charAt(0).toUpperCase() + String(val).slice(1); } // [{l: "x", r: Double}, {l: "y", r: Double}] => (Double × (Double × Unit)) export const structType = fields => { if (fields.length === 0) { return Unit; } const [field, ...rest] = fields; const fieldType = getRight(field); return prodType(fieldType)(structType(rest)); }; export const makeConstructor = fields => { const internal = (nParams, ret) => { if (nParams === 0) { const result = ret(unit); return result; } return nextParam => { const wrappedName = 'wrapped_' + ret.name; const newRet = { [wrappedName]: inner => constructorProduct(nextParam)(ret(inner)), }[wrappedName]; return internal(nParams-1, newRet); } }; const id = x => x; return internal(fields.length, id); }; export const makeConstructorType = type => fields => { if (fields.length === 0) { return type; } const [field, ...rest] = fields; const fieldType = getRight(field); return fnType(fieldType)(makeConstructorType(rest)); }; export const makeGetters = fields => { if (fields.length === 0) { return []; } const [field, ...rest] = fields; const fieldName = getLeft(field); const getterName = `get${capitalizeFirstLetter(fieldName)}`; return [ { [getterName]: obj => getLeft(obj) }[getterName], ...makeGetters(rest).map(getter => ({[getter.name]: obj => getter(getRight(obj))}[getter.name])), ]; }; export const makeGettersTypes = type => fields => { return fields.map(field => { const fieldType = getRight(field); return fnType(type)(fieldType); }); };