restructure code a bit, add comparison functions for primitive types and composed types (needed to put values in sets)

This commit is contained in:
Joeri Exelmans 2025-04-17 15:11:06 +02:00
parent 3978f7f835
commit 8653bb99c6
12 changed files with 175 additions and 64 deletions

View file

@ -6,12 +6,20 @@ import { lsType } from "./types.js";
import { Typed } from "../typed.js"
// 'normal' implementation
const emptyList = {l:[]};
export const emptyList = {l:[]};
const emptyListType = makeGeneric(a => lsType(a));
const get = ls => i => ls.l[i];
const put = ls => i => elem => ({l: ls.l.with(Number(i), elem)});
const push = ls => elem => ({l:ls.l.concat([elem])});
const map = ls => fn => ({ l: ls.l.map(elem => fn(elem)) });
export const get = ls => i => ls.l[i];
export const put = ls => i => elem => ({l: ls.l.with(Number(i), elem)});
export const push = ls => elem => ({l:ls.l.concat([elem])});
export const map = ls => fn => ({ l: ls.l.map(elem => fn(elem)) });
export const length = ls => ls.l.length;
export const fold = ls => callback => initial => {
let acc = initial;
for (let i=0; i<ls.l.length; i++) {
acc = callback(acc)(ls.l[i]);
}
return acc;
}
export const String = lsType(Char); // alias
export const Module = lsType(Typed);

View file

@ -1,3 +1,7 @@
// Product-type (also called: pair, tuple)
// A Product-type always has only two fields, called "left" and "right".
// Product-types of more fields (called Structs) can be constructed by nesting Product-types.
import { makeGeneric } from "../generics/generics.js";
import { GenericType, Type } from "../primitives/types.js";
import { typedFnType } from "./types.js";

View file

@ -24,6 +24,20 @@ export const emptySet = compareFn => new RBTreeWrapper(createRBTree((x, y) => co
export const has = set => key => set.tree.get(key) === true;
export const add = set => key => set.tree.get(key) === true ? set : new RBTreeWrapper(set.tree.insert(key, true));
export const remove = set => key => new RBTreeWrapper(set.tree.remove(key));
export const length = set => set.tree.length;
export const first = set => set.tree.begin;
export const last = set => set.tree.end;
// test if iterator is 'done', and if not, get element and advance iterator.
export const read = iter => ifNotDone => ifDone => {
if (iter !== undefined && iter.valid) {
return ifNotDone(iter.key)(iter.clone().next());
}
else {
return ifDone();
}
};
export const forEach = set => fn => {
set.tree.forEach(key => { fn(key); });

View file

@ -7,7 +7,10 @@ function capitalizeFirstLetter(val) {
return String(val).charAt(0).toUpperCase() + String(val).slice(1);
}
// [{l: "x", r: Double}, {l: "y", r: Double}] => (Double × (Double × Unit))
// 'fields' is an array of (name: string, type: Type) pairs.
// e.g.:
// [{l: "x", r: Double}, {l: "y", r: Double}]
// results in the type (Double × (Double × Unit))
export const structType = fields => {
if (fields.length === 0) {
return Unit;

View file

@ -1,17 +1,22 @@
// Sum-type (also called: tagged union, disjoin union, variant type)
// A Sum-type always has only two variants, called "left" and "right".
// Sum-types of more variants (called Enums) can be constructed by nesting Sum-types.
import { prodType } from "./types.js";
import { GenericType, Type } from "../primitives/types.js";
import { typedFnType } from "./types.js";
import { makeGeneric } from "../generics/generics.js";
import { sumType } from "./types.js";
export const constructorLeft = left => ({variant: "L", value: left });
export const constructorRight = right => ({variant: "R", value: right});
export const constructorLeft = left => ({t: "L", v: left }); // 't': tag, 'v': value
export const constructorRight = right => ({t: "R", v: right});
// signature:
// sum-type -> (leftType -> resultType, rightType -> resultType) -> resultType
export const match = sum => handlers => sum.variant === "L"
? handlers.left(sum.value)
: handlers.right(sum.value);
export const match = sum => handlers =>
sum.t === "L"
? handlers.left(sum.v)
: handlers.right(sum.v);
export const ModuleSum = {l:[
// binary type constructor