Compare commits
No commits in common. "8a4b47df02a5cebd4b39015e450c4d793e3962fe" and "d9111c396912ee2a030ba4c87f18bcf222a53b3d" have entirely different histories.
8a4b47df02
...
d9111c3969
28 changed files with 100 additions and 181 deletions
|
|
@ -1,19 +0,0 @@
|
||||||
import { compareTypes } from "../lib/compare/type.js";
|
|
||||||
import { ModuleStd } from "../lib/stdlib.js";
|
|
||||||
import { emptyDict, get, set } from "../lib/structures/dict.js";
|
|
||||||
import { emptySet, add } from "../lib/structures/set.js";
|
|
||||||
import { makeCompareFn } from "../lib/compare/dynamic.js"
|
|
||||||
|
|
||||||
// console.log(ModuleStd);
|
|
||||||
|
|
||||||
const typeDict = ModuleStd.reduce((typeDict, {i, t}) => {
|
|
||||||
try {
|
|
||||||
const instances = get(typeDict)(t) || emptySet(makeCompareFn(t));
|
|
||||||
return set(typeDict)(t)(add(instances)(i));
|
|
||||||
} catch (e) {
|
|
||||||
console.log('warning:',e.message);
|
|
||||||
return typeDict;
|
|
||||||
}
|
|
||||||
}, emptyDict(compareTypes));
|
|
||||||
|
|
||||||
console.log(typeDict);
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { DefaultMap } from "../lib/util/defaultmap.js";
|
||||||
import { pretty } from '../lib/util/pretty.js';
|
import { pretty } from '../lib/util/pretty.js';
|
||||||
import { isFunction } from '../structures/types.js';
|
import { isFunction } from '../structures/types.js';
|
||||||
import { ModuleStd } from '../lib/stdlib.js';
|
import { ModuleStd } from '../lib/stdlib.js';
|
||||||
import { Double, GenericType, Int, UUID, Type } from "../primitives/types.js";
|
import { Double, GenericType, Int, SymbolT, Type } from "../primitives/types.js";
|
||||||
import { eqType } from '../primitives/type.js';
|
import { eqType } from '../primitives/type.js';
|
||||||
import { Top } from "../primitives/types.js";
|
import { Top } from "../primitives/types.js";
|
||||||
import { assignFn, makeGeneric, onlyOccurring } from '../lib/generics/generics.js';
|
import { assignFn, makeGeneric, onlyOccurring } from '../lib/generics/generics.js';
|
||||||
|
|
@ -287,7 +287,7 @@ async function createInstance(t) {
|
||||||
});
|
});
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
else if (eqType(t)(UUID)) {
|
else if (eqType(t)(SymbolT)) {
|
||||||
console.log("Note: you are creating a new Symbol. Even if the description matches that of another symbol (e.g., \"Int\"), a new Symbol will be created that is unique and only equal to itself.");
|
console.log("Note: you are creating a new Symbol. Even if the description matches that of another symbol (e.g., \"Int\"), a new Symbol will be created that is unique and only equal to itself.");
|
||||||
const symbolDescr = await input({message: "enter symbol description:"});
|
const symbolDescr = await input({message: "enter symbol description:"});
|
||||||
return symbolDescr + '__' + genUUID(16);
|
return symbolDescr + '__' + genUUID(16);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import { getInst, getType } from "../primitives/dynamic.js";
|
import { getInst, getType } from "../primitives/dynamic.js";
|
||||||
import { SymbolBool, SymbolBottom, SymbolByte, SymbolChar, SymbolDouble, SymbolDynamic, SymbolInt, SymbolUUID, SymbolType, SymbolUnit } from "../primitives/primitive_types.js";
|
import { SymbolBool, SymbolBottom, SymbolByte, SymbolChar, SymbolDouble, SymbolDynamic, SymbolInt, SymbolUUID, SymbolType, SymbolUnit } from "../primitives/primitive_types.js";
|
||||||
import { UNBOUND_SYMBOLS } from "../primitives/typevars.js";
|
|
||||||
import { symbolDict, symbolFunction, symbolList, symbolProduct, symbolSet, symbolSum } from "../structures/type_constructors.js";
|
import { symbolDict, symbolFunction, symbolList, symbolProduct, symbolSet, symbolSum } from "../structures/type_constructors.js";
|
||||||
import { prettyT } from "../util/pretty.js";
|
|
||||||
import { compareBools, compareNumbers, compareStrings, compareSymbols, compareUnits } from "./primitives.js";
|
import { compareBools, compareNumbers, compareStrings, compareSymbols, compareUnits } from "./primitives.js";
|
||||||
import { compareDicts, compareFunctions, compareLists, compareProducts, compareSets, compareSums } from "./structures.js";
|
import { compareDicts, compareFunctions, compareLists, compareProducts, compareSets, compareSums } from "./structures.js";
|
||||||
import { compareTypes } from "./type.js";
|
import { compareTypes } from "./type.js";
|
||||||
|
|
@ -11,8 +9,6 @@ export const compareDynamic = x => y =>
|
||||||
compareTypes(getType(x))(getType(y))
|
compareTypes(getType(x))(getType(y))
|
||||||
|| makeCompareFn(getType(x))(getInst(x))(getInst(y));
|
|| makeCompareFn(getType(x))(getInst(x))(getInst(y));
|
||||||
|
|
||||||
const cannotCompareTypeVarInstances = _ => _ => { throw new Error("Cannot compare instance of type variables"); }
|
|
||||||
|
|
||||||
const typeSymbolToCmp = new Map([
|
const typeSymbolToCmp = new Map([
|
||||||
[SymbolInt , compareNumbers],
|
[SymbolInt , compareNumbers],
|
||||||
[SymbolBool , compareBools],
|
[SymbolBool , compareBools],
|
||||||
|
|
@ -21,7 +17,7 @@ const typeSymbolToCmp = new Map([
|
||||||
[SymbolChar , compareStrings],
|
[SymbolChar , compareStrings],
|
||||||
[SymbolUnit , compareUnits],
|
[SymbolUnit , compareUnits],
|
||||||
[SymbolBottom , _ => _ => { throw new Error("Bottom!"); }],
|
[SymbolBottom , _ => _ => { throw new Error("Bottom!"); }],
|
||||||
[SymbolUUID , compareSymbols],
|
[SymbolUUID , compareSymbols],
|
||||||
// [SymbolGenericType, ?] TODO
|
// [SymbolGenericType, ?] TODO
|
||||||
[SymbolType , compareTypes],
|
[SymbolType , compareTypes],
|
||||||
[SymbolDynamic, compareDynamic],
|
[SymbolDynamic, compareDynamic],
|
||||||
|
|
@ -33,20 +29,11 @@ const typeSymbolToCmp = new Map([
|
||||||
[symbolList , compareLists],
|
[symbolList , compareLists],
|
||||||
[symbolSet , compareSets],
|
[symbolSet , compareSets],
|
||||||
[symbolDict , compareDicts],
|
[symbolDict , compareDicts],
|
||||||
|
|
||||||
// even though we cannot compare typevar instances,
|
|
||||||
// we still need to give a function or shit will break
|
|
||||||
// types that contain typevars are never instantiated,
|
|
||||||
// EXCEPT:
|
|
||||||
// - generic functions (but for function comparison we don't look at the in/out types)
|
|
||||||
// - empty list, empty set, empty dict are all generic, but for each type there is only one empty element, so it never needs to be compared to another one
|
|
||||||
...UNBOUND_SYMBOLS.map(uuid => [uuid, cannotCompareTypeVarInstances]),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const makeCompareFn = type => {
|
export const makeCompareFn = type => {
|
||||||
return type.params.reduce(
|
return type.params.reduce(
|
||||||
(acc, cur) => acc(makeCompareFn(cur(type))),
|
(acc, cur) => acc(makeCompareFn(cur(type))),
|
||||||
typeSymbolToCmp.get(type.symbol)
|
typeSymbolToCmp.get(type.symbol)
|
||||||
|| (() => { throw new Error(`don't know how to compare instances of '${prettyT(type)}'`); })()
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,6 @@ import { compareDynamic, makeCompareFn } from "./dynamic.js";
|
||||||
const mkType = getDefaultTypeParser();
|
const mkType = getDefaultTypeParser();
|
||||||
|
|
||||||
export const ModuleCompareDynamic = [
|
export const ModuleCompareDynamic = [
|
||||||
{i: makeCompareFn , t: mkType("Type -> a -> a -> Int")},
|
{i: makeCompareFn , t: mkType("∀a: Type -> a -> a -> Int")},
|
||||||
{i: compareDynamic, t: mkType("Dynamic -> Dynamic -> Int")},
|
{i: compareDynamic, t: mkType("Dynamic -> Dynamic -> Int")},
|
||||||
];
|
];
|
||||||
|
|
@ -7,5 +7,5 @@ export const ModuleComparePrimitives = [
|
||||||
{i: compareNumbers, t: mkType("Double -> Double -> Int")},
|
{i: compareNumbers, t: mkType("Double -> Double -> Int")},
|
||||||
{i: compareBools , t: mkType("Bool -> Bool -> Int")},
|
{i: compareBools , t: mkType("Bool -> Bool -> Int")},
|
||||||
{i: compareUnits , t: mkType("Unit -> Unit -> Int")},
|
{i: compareUnits , t: mkType("Unit -> Unit -> Int")},
|
||||||
{i: compareSymbols, t: mkType("UUID -> UUID -> Int")},
|
{i: compareSymbols, t: mkType("SymbolT -> SymbolT -> Int")},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@ import { compareDicts, compareLists, compareProducts, compareSets, compareSums }
|
||||||
const mkType = getDefaultTypeParser();
|
const mkType = getDefaultTypeParser();
|
||||||
|
|
||||||
export const ModuleCompareStructures = [
|
export const ModuleCompareStructures = [
|
||||||
{i: compareLists, t: mkType("(a -> a -> Int) -> [a] -> [a] -> Int")},
|
{i: compareLists, t: mkType("∀a: (a -> a -> Int) -> [a] -> [a] -> Int")},
|
||||||
|
|
||||||
{i: compareProducts, t: mkType("(a -> a -> Int) -> (b -> b -> Int) -> (a*b) -> (a*b) -> Int")},
|
{i: compareProducts, t: mkType("∀a,b: (a -> a -> Int) -> (b -> b -> Int) -> (a*b) -> (a*b) -> Int")},
|
||||||
|
|
||||||
{i: compareSums, t: mkType("(a -> a -> Int) -> (b -> b -> Int) -> (a+b) -> (a+b) -> Int")},
|
{i: compareSums, t: mkType("∀a,b: (a -> a -> Int) -> (b -> b -> Int) -> (a+b) -> (a+b) -> Int")},
|
||||||
|
|
||||||
{i: compareSets, t: mkType("(a -> a -> Int) -> {a} -> {a} -> Int")},
|
{i: compareSets, t: mkType("∀a: (a -> a -> Int) -> {a} -> {a} -> Int")},
|
||||||
|
|
||||||
{i: compareDicts, t: mkType("(a -> a -> Int) -> (b -> b-> Int) -> (a => b) -> (a => b) -> Int")}
|
{i: compareDicts, t: mkType("∀a,b: (a -> a -> Int) -> (b -> b-> Int) -> (a => b) -> (a => b) -> Int")}
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { isTypeVar, TYPE_VARS } from "../primitives/typevars.js";
|
||||||
|
|
||||||
// helper for creating generic types
|
// helper for creating generic types
|
||||||
// for instance, the type:
|
// for instance, the type:
|
||||||
// a -> a -> Bool
|
// ∀a: a -> a -> Bool
|
||||||
// is created by
|
// is created by
|
||||||
// makeGeneric(a => fnType(() => a)(() => fnType(() => a)(() => Bool)))
|
// makeGeneric(a => fnType(() => a)(() => fnType(() => a)(() => Bool)))
|
||||||
export const makeGeneric = callback => {
|
export const makeGeneric = callback => {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
import { getHumanReadableName } from "../primitives/symbol.js";
|
import { getHumanReadableName } from "../primitives/symbol.js";
|
||||||
import { inspect } from "util";
|
|
||||||
import { prettyT } from "../util/pretty.js";
|
|
||||||
|
|
||||||
const __makeTypeConstructor = (symbol, nAry, params) => {
|
const __makeTypeConstructor = (symbol, nAry, params) => {
|
||||||
if (nAry === 0) {
|
if (nAry === 0) {
|
||||||
return {
|
return { symbol, params };
|
||||||
symbol, params,
|
|
||||||
[inspect.custom](depth, options, inspect){ return options.stylize(prettyT(this), 'null'); },
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
// only for debugging, do we give the function a name
|
// only for debugging, do we give the function a name
|
||||||
const fName = `${getHumanReadableName(symbol).toLowerCase()}Type${params.length>0?params.length:''}`;
|
const fName = `${getHumanReadableName(symbol).toLowerCase()}Type${params.length>0?params.length:''}`;
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,5 @@ const mkType = getDefaultTypeParser();
|
||||||
|
|
||||||
export const ModuleTypeConstructor = [
|
export const ModuleTypeConstructor = [
|
||||||
// Problem: number of parameters of returned function depends on the 'Int' parameter...
|
// Problem: number of parameters of returned function depends on the 'Int' parameter...
|
||||||
// {i: makeTypeConstructor, t: mkType("UUID -> Int -> ??")}
|
// {i: makeTypeConstructor, t: mkType("SymbolT -> Int -> ??")}
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,8 @@ import { Dynamic } from "../primitives/primitive_types.js";
|
||||||
import { getHumanReadableName } from "../primitives/symbol.js";
|
import { getHumanReadableName } from "../primitives/symbol.js";
|
||||||
import { getSymbol } from "../primitives/type.js";
|
import { getSymbol } from "../primitives/type.js";
|
||||||
import { TYPE_VARS } from "../primitives/typevars.js";
|
import { TYPE_VARS } from "../primitives/typevars.js";
|
||||||
import { dictType, fnType, lsType, prodType, sumType } from "../structures/type_constructors.types.js";
|
import { dictType, fnType, lsType, prodType, sumType } from "../structures/type_constructors.js";
|
||||||
import { setType } from "../structures/type_constructors.types.js";
|
import { setType } from "../structures/type_constructors.js";
|
||||||
|
|
||||||
// A very stupid little parser, that can only parse:
|
|
||||||
// - primitives => simply maps onto types.
|
|
||||||
// - things between brackets => calls a type constructor that takes one parameter on whatever is between the brackets.
|
|
||||||
// - binary (infix) operators => calls a type constructor that takes two parameters on the LHS and RHS.
|
|
||||||
|
|
||||||
export const makeTypeParser = ({
|
export const makeTypeParser = ({
|
||||||
// parser can be extended:
|
// parser can be extended:
|
||||||
|
|
@ -54,6 +49,13 @@ export const makeTypeParser = ({
|
||||||
['⇒', dictType],
|
['⇒', dictType],
|
||||||
['=>', dictType],
|
['=>', dictType],
|
||||||
|
|
||||||
|
// only used for type variables (e.g., ∀a,b,c:)
|
||||||
|
[',', fnX => fnY => {
|
||||||
|
const x = fnX();
|
||||||
|
const y = fnY();
|
||||||
|
return Array.isArray(x) ? x.concat(y) : [x].concat(y)
|
||||||
|
}],
|
||||||
|
|
||||||
...extraInfixOperators,
|
...extraInfixOperators,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,3 @@
|
||||||
import { assignFn } from "../generics/generics.js";
|
|
||||||
|
|
||||||
export const newDynamic = i => t => ({i, t});
|
export const newDynamic = i => t => ({i, t});
|
||||||
|
|
||||||
export const getInst = lnk => lnk.i;
|
export const getInst = lnk => lnk.i;
|
||||||
export const getType = lnk => lnk.t;
|
export const getType = lnk => lnk.t;
|
||||||
|
|
||||||
export const apply = input => fun => {
|
|
||||||
const inputType = getType(input)
|
|
||||||
const funType = getType(fun);
|
|
||||||
const outputType = assignFn(funType, inputType);
|
|
||||||
|
|
||||||
const inputValue = getInst(input);
|
|
||||||
const funValue = getInst(fun);
|
|
||||||
const outputValue = funValue(inputValue);
|
|
||||||
|
|
||||||
return newDynamic(outputValue, outputType);
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,14 @@
|
||||||
import { getDefaultTypeParser } from "../parser/type_parser.js";
|
import { getDefaultTypeParser } from "../parser/type_parser.js";
|
||||||
import { apply, getInst, getType, newDynamic } from "./dynamic.js";
|
import { getInst, getType, newDynamic } from "./dynamic.js";
|
||||||
|
|
||||||
const mkType = getDefaultTypeParser();
|
const mkType = getDefaultTypeParser();
|
||||||
|
|
||||||
export const ModuleDynamic = [
|
export const ModuleDynamic = [
|
||||||
{ i: newDynamic, t: mkType("a -> Type -> Dynamic")},
|
{ i: newDynamic, t: mkType("∀a: a -> Type -> Dynamic")},
|
||||||
|
|
||||||
// allows us to (unsafely) cast the result to the specific type...
|
// allows us to (unsafely) cast the result to the specific type...
|
||||||
// (not sure if this is the right way to go)
|
// (not sure if this is the right way to go)
|
||||||
{ i: getInst, t: mkType("Dynamic -> a") },
|
{ i: getInst, t: mkType("∀a: Dynamic -> a") },
|
||||||
|
|
||||||
{ i: getType, t: mkType("Dynamic -> Type") },
|
{ i: getType, t: mkType("Dynamic -> Type") },
|
||||||
|
|
||||||
{ i: apply, t: mkType("Dynamic -> Dynamic -> Dynamic") },
|
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,6 @@ import { eqSymbol, getHumanReadableName } from "./symbol.js";
|
||||||
const mkType = getDefaultTypeParser();
|
const mkType = getDefaultTypeParser();
|
||||||
|
|
||||||
export const ModuleSymbol = [
|
export const ModuleSymbol = [
|
||||||
{ i: getHumanReadableName, t: mkType("UUID -> String")},
|
{ i: getHumanReadableName, t: mkType("SymbolT -> String")},
|
||||||
{ i: eqSymbol, t: mkType("UUID -> UUID -> Bool")},
|
{ i: eqSymbol, t: mkType("SymbolT -> SymbolT -> Bool")},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,6 @@ const mkType = getDefaultTypeParser();
|
||||||
// each 'typed object' is implicitly an instance of TypeLink (defined below)
|
// each 'typed object' is implicitly an instance of TypeLink (defined below)
|
||||||
export const ModuleType = [
|
export const ModuleType = [
|
||||||
{i: eqType , t: mkType("Type -> Type -> Bool")},
|
{i: eqType , t: mkType("Type -> Type -> Bool")},
|
||||||
{i: getSymbol, t: mkType("Type -> UUID")},
|
{i: getSymbol, t: mkType("Type -> SymbolT")},
|
||||||
{i: getParams, t: mkType("Type -> [Type -> Type]")},
|
{i: getParams, t: mkType("Type -> [Type -> Type]")},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,3 @@
|
||||||
import { inspect } from "node:util";
|
export const unit = {};
|
||||||
|
|
||||||
export const unit = {
|
|
||||||
[inspect.custom](depth, options, inspect){ return '()'; }
|
|
||||||
};
|
|
||||||
|
|
||||||
export const eqUnit = _ => _ => true;
|
export const eqUnit = _ => _ => true;
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,12 @@
|
||||||
import { RBTreeWrapper } from "../util/rbtree_wrapper.js";
|
import { RBTreeWrapper } from "../util/rbtree_wrapper.js";
|
||||||
import { indent } from "../util/util.js";
|
|
||||||
import { newProduct } from "./product.js";
|
import { newProduct } from "./product.js";
|
||||||
import { newLeft, newRight } from "./sum.js";
|
import { newLeft, newRight } from "./sum.js";
|
||||||
|
|
||||||
// only for debugging
|
export const emptyDict = compareFn => RBTreeWrapper.new((x, y) => compareFn(x)(y));
|
||||||
function inspectDict(_depth, options, inspect) {
|
|
||||||
const entries = [];
|
|
||||||
this.tree.forEach((key, val) => { entries.push(`${inspect(key, options)} => ${inspect(val, options)}`); });
|
|
||||||
return `{\n${indent(entries.join(',\n'),2)}\n}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const emptyDict = compareFn => RBTreeWrapper.new((x, y) => compareFn(x)(y), inspectDict);
|
export const has = dict => key => dict.tree.get(key) === true;
|
||||||
|
export const set = dict => key => value => new RBTreeWrapper(dict.tree.remove(key).insert(key, value));
|
||||||
export const has = dict => key => dict.tree.get(key) !== undefined;
|
export const remove = dict => key => new RBTreeWrapper(dict.tree.remove(key));
|
||||||
export const get = dict => key => dict.tree.get(key);
|
|
||||||
export const set = dict => key => value => new RBTreeWrapper(dict.tree.remove(key).insert(key, value), inspectDict);
|
|
||||||
export const remove = dict => key => new RBTreeWrapper(dict.tree.remove(key), inspectDict);
|
|
||||||
export const length = dict => dict.tree.length;
|
export const length = dict => dict.tree.length;
|
||||||
|
|
||||||
export const first = dict => dict.tree.begin;
|
export const first = dict => dict.tree.begin;
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,19 @@ import { makeTypeParser } from "../parser/type_parser.js";
|
||||||
import { makeTypeConstructor } from "../meta/type_constructor.js";
|
import { makeTypeConstructor } from "../meta/type_constructor.js";
|
||||||
import { emptyDict, first, has, last, length, read, remove, set } from "./dict.js";
|
import { emptyDict, first, has, last, length, read, remove, set } from "./dict.js";
|
||||||
|
|
||||||
export const symbolDictIterator = 'DictIterator__d9d175b6bfd1283f00851a99787d0499';
|
const dictIterator = makeTypeConstructor('DictIterator__d9d175b6bfd1283f00851a99787d0499')(2);
|
||||||
|
|
||||||
const dictIterator = makeTypeConstructor(symbolDictIterator)(2);
|
|
||||||
|
|
||||||
const mkType = makeTypeParser({
|
const mkType = makeTypeParser({
|
||||||
// we invent a bit of syntax for the dict iterator type, which takes two type parameters (key and value)
|
|
||||||
extraInfixOperators: [['|=>|', dictIterator]],
|
extraInfixOperators: [['|=>|', dictIterator]],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ModuleDict = [
|
export const ModuleDict = [
|
||||||
{ i: emptyDict , t: mkType("(a -> a -> Int) -> (a => b)") },
|
{ i: emptyDict , t: mkType("∀a,b: (a -> a -> Int) -> (a => b)") },
|
||||||
{ i: has , t: mkType("(a => b) -> a -> Bool")},
|
{ i: has , t: mkType("∀a,b: (a => b) -> a -> Bool")},
|
||||||
{ i: set , t: mkType("(a => b) -> a -> b -> (a => b)")},
|
{ i: set , t: mkType("∀a,b: (a => b) -> a -> b -> (a => b)")},
|
||||||
{ i: remove , t: mkType("(a => b) -> a -> (a => b)")},
|
{ i: remove , t: mkType("∀a,b: (a => b) -> a -> (a => b)")},
|
||||||
{ i: length , t: mkType("(a => b) -> Int")},
|
{ i: length , t: mkType("∀a,b: (a => b) -> Int")},
|
||||||
{ i: first , t: mkType("(a => b) -> (a |=>| b)")},
|
{ i: first , t: mkType("∀a,b: (a => b) -> (a |=>| b)")},
|
||||||
{ i: last , t: mkType("(a => b) -> (a |=>| b)")},
|
{ i: last , t: mkType("∀a,b: (a => b) -> (a |=>| b)")},
|
||||||
{ i: read , t: mkType("(a |=>| b) -> (Unit + ((a*b) * (a |=>| b)))")},
|
{ i: read , t: mkType("∀a,b: (a |=>| b) -> (Unit + ((a*b) * (a |=>| b)))")},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ import { emptyList, fold, get, length, map, pop, push, put } from "./list.js";
|
||||||
const mkType = getDefaultTypeParser();
|
const mkType = getDefaultTypeParser();
|
||||||
|
|
||||||
export const ModuleList = [
|
export const ModuleList = [
|
||||||
{ i: emptyList, t: mkType("[a]")},
|
{ i: emptyList, t: mkType("∀a: [a]")},
|
||||||
{ i: get , t: mkType("[a] -> Int -> a")},
|
{ i: get , t: mkType("∀a: [a] -> Int -> a")},
|
||||||
{ i: put , t: mkType("[a] -> Int -> a -> [a]")},
|
{ i: put , t: mkType("∀a: [a] -> Int -> a -> [a]")},
|
||||||
{ i: push , t: mkType("[a] -> a -> [a]")},
|
{ i: push , t: mkType("∀a: [a] -> a -> [a]")},
|
||||||
{ i: pop , t: mkType("[a] -> a")},
|
{ i: pop , t: mkType("∀a: [a] -> a")},
|
||||||
{ i: map , t: mkType("[a] -> (a -> b) -> [b]")},
|
{ i: map , t: mkType("∀a: [a] -> (a -> b) -> [b]")},
|
||||||
{ i: length , t: mkType("[a] -> Int")},
|
{ i: length , t: mkType("∀a: [a] -> Int")},
|
||||||
{ i: fold , t: mkType("[a] -> (b -> a -> b) -> b -> b")},
|
{ i: fold , t: mkType("∀a: [a] -> (b -> a -> b) -> b -> b")},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { newProduct, getLeft, getRight } from "./product.js";
|
||||||
const mkType = getDefaultTypeParser();
|
const mkType = getDefaultTypeParser();
|
||||||
|
|
||||||
export const ModuleProduct = [
|
export const ModuleProduct = [
|
||||||
{ i: newProduct, t: mkType("a -> b -> (a * b)") },
|
{ i: newProduct, t: mkType("∀a,b: a -> b -> (a * b)") },
|
||||||
{ i: getLeft , t: mkType("(a * b) -> a" ) },
|
{ i: getLeft , t: mkType("∀a,b: (a * b) -> a" ) },
|
||||||
{ i: getRight , t: mkType("(a * b) -> b" ) },
|
{ i: getRight , t: mkType("∀a,b: (a * b) -> b" ) },
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -2,21 +2,13 @@ import { newRight } from "./sum.js";
|
||||||
import { newProduct } from "./product.js";
|
import { newProduct } from "./product.js";
|
||||||
import { unit } from "../primitives/unit.js";
|
import { unit } from "../primitives/unit.js";
|
||||||
import { RBTreeWrapper } from "../util/rbtree_wrapper.js";
|
import { RBTreeWrapper } from "../util/rbtree_wrapper.js";
|
||||||
import { indent } from "../util/util.js";
|
|
||||||
|
|
||||||
// only for debugging
|
|
||||||
function inspectSet(_depth, options, inspect) {
|
|
||||||
const keys = [];
|
|
||||||
this.tree.forEach((key) => { keys.push(inspect(key, options)); });
|
|
||||||
return `{\n${indent(keys.join(',\n'), 2)}\n}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// (a -> a -> Int) -> Set(a)
|
// (a -> a -> Int) -> Set(a)
|
||||||
export const emptySet = compareFn => RBTreeWrapper.new((x, y) => compareFn(x)(y), inspectSet);
|
export const emptySet = compareFn => RBTreeWrapper.new((x, y) => compareFn(x)(y));
|
||||||
|
|
||||||
export const has = set => key => set.tree.get(key) === true;
|
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), inspectSet);
|
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), inspectSet);
|
export const remove = set => key => new RBTreeWrapper(set.tree.remove(key));
|
||||||
export const length = set => set.tree.length;
|
export const length = set => set.tree.length;
|
||||||
|
|
||||||
export const fold = set => callback => initial => {
|
export const fold = set => callback => initial => {
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,20 @@ import { makeTypeParser } from "../parser/type_parser.js";
|
||||||
import { makeTypeConstructor } from "../meta/type_constructor.js";
|
import { makeTypeConstructor } from "../meta/type_constructor.js";
|
||||||
import { emptySet, has, add, remove, length, first, read, last, fold } from "./set.js";
|
import { emptySet, has, add, remove, length, first, read, last, fold } from "./set.js";
|
||||||
|
|
||||||
export const symbolSetIterator = 'SetIterator__f6b0ddd78ed41c58e5a442f2681da011';
|
const setIterator = makeTypeConstructor('SetIterator__f6b0ddd78ed41c58e5a442f2681da011')(1);
|
||||||
|
|
||||||
const setIterator = makeTypeConstructor(symbolSetIterator)(1);
|
|
||||||
|
|
||||||
const mkType = makeTypeParser({
|
const mkType = makeTypeParser({
|
||||||
extraBracketOperators: [['<', ['>', setIterator]]],
|
extraBracketOperators: [['<', ['>', setIterator]]],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ModuleSet = [
|
export const ModuleSet = [
|
||||||
{ i: emptySet , t: mkType("(a -> a -> Int) -> {a}") },
|
{ i: emptySet , t: mkType("∀a: (a -> a -> Int) -> {a}") },
|
||||||
{ i: has , t: mkType("{a} -> a -> Bool")},
|
{ i: has , t: mkType("∀a: {a} -> a -> Bool")},
|
||||||
{ i: add , t: mkType("{a} -> a -> {a}")},
|
{ i: add , t: mkType("∀a: {a} -> a -> {a}")},
|
||||||
{ i: remove , t: mkType("{a} -> a -> {a}")},
|
{ i: remove , t: mkType("∀a: {a} -> a -> {a}")},
|
||||||
{ i: length , t: mkType("{a} -> Int")},
|
{ i: length , t: mkType("∀a: {a} -> Int")},
|
||||||
{ i: fold , t: mkType("{a} -> (b -> a -> b) -> b")},
|
{ i: fold , t: mkType("∀a,b: {a} -> (b -> a -> b) -> b")},
|
||||||
{ i: first , t: mkType("{a} -> <a>")},
|
{ i: first , t: mkType("∀a: {a} -> <a>")},
|
||||||
{ i: last , t: mkType("{a} -> <a>")},
|
{ i: last , t: mkType("∀a: {a} -> <a>")},
|
||||||
{ i: read , t: mkType("<a> -> (Unit + (a * <a>))")},
|
{ i: read , t: mkType("∀a: <a> -> (Unit + (a * <a>))")},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { match, newLeft, newRight } from "./sum.js";
|
||||||
const mkType = getDefaultTypeParser();
|
const mkType = getDefaultTypeParser();
|
||||||
|
|
||||||
export const ModuleSum = [
|
export const ModuleSum = [
|
||||||
{ i: newLeft , t: mkType("a -> (a + b)") },
|
{ i: newLeft , t: mkType("∀a,b: a -> (a + b)") },
|
||||||
{ i: newRight , t: mkType("b -> (a + b)") },
|
{ i: newRight , t: mkType("∀a,b: b -> (a + b)") },
|
||||||
{ i: match , t: mkType("(a + b) -> (a -> c) -> (b -> c) -> c") },
|
{ i: match , t: mkType("∀a,b,c: (a + b) -> (a -> c) -> (b -> c) -> c") },
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,17 @@
|
||||||
// to break up dependency cycles, type constructors are defined in their own JS module
|
// to break up dependency cycles, type constructors are defined in their own JS module
|
||||||
|
|
||||||
|
import { makeTypeConstructor } from "../meta/type_constructor.js";
|
||||||
|
|
||||||
export const symbolFunction = "Function__c2433e31fa574a2cb3b6b5d62ac9d4b2";
|
export const symbolFunction = "Function__c2433e31fa574a2cb3b6b5d62ac9d4b2";
|
||||||
export const symbolSum = "Sum__89b731efa6344ea0b6a8663a45cf3ea8";
|
export const symbolSum = "Sum__89b731efa6344ea0b6a8663a45cf3ea8";
|
||||||
export const symbolProduct = "Product__89351ecdedfb4b05b2a5a6cc0c383e12";
|
export const symbolProduct = "Product__89351ecdedfb4b05b2a5a6cc0c383e12";
|
||||||
export const symbolList = "List__daa8de8a9047435e96034ec64f2da3a1";
|
export const symbolList = "List__daa8de8a9047435e96034ec64f2da3a1";
|
||||||
export const symbolSet = "Set__8fef2c1873df4327ac31bd61d2ecf7e0";
|
export const symbolSet = "Set__8fef2c1873df4327ac31bd61d2ecf7e0";
|
||||||
export const symbolDict = "Dict__d7158547322549ac9f7f8176aec123dd";
|
export const symbolDict = "Dict__d7158547322549ac9f7f8176aec123dd";
|
||||||
|
|
||||||
|
export const fnType = makeTypeConstructor(symbolFunction)(2);
|
||||||
|
export const sumType = makeTypeConstructor(symbolSum)(2);
|
||||||
|
export const prodType = makeTypeConstructor(symbolProduct)(2);
|
||||||
|
export const lsType = makeTypeConstructor(symbolList)(1);
|
||||||
|
export const setType = makeTypeConstructor(symbolSet)(1);
|
||||||
|
export const dictType = makeTypeConstructor(symbolDict)(2);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
import { makeTypeConstructor } from "../meta/type_constructor.js";
|
import { getDefaultTypeParser } from "../parser/type_parser.js";
|
||||||
import { Type, UUID } from "../primitives/primitive_types.js";
|
import { UUID } from "../primitives/primitive_types.js";
|
||||||
import { symbolDict, symbolFunction, symbolList, symbolProduct, symbolSet, symbolSum } from "./type_constructors.js";
|
import { dictType, fnType, lsType, prodType, setType, sumType, symbolDict, symbolFunction, symbolList, symbolProduct, symbolSet, symbolSum } from "./type_constructors.js";
|
||||||
|
|
||||||
export const fnType = makeTypeConstructor(symbolFunction)(2);
|
const mkType = getDefaultTypeParser();
|
||||||
export const sumType = makeTypeConstructor(symbolSum)(2);
|
|
||||||
export const prodType = makeTypeConstructor(symbolProduct)(2);
|
|
||||||
export const lsType = makeTypeConstructor(symbolList)(1);
|
|
||||||
export const setType = makeTypeConstructor(symbolSet)(1);
|
|
||||||
export const dictType = makeTypeConstructor(symbolDict)(2);
|
|
||||||
|
|
||||||
export const ModuleStructuralSymbols = [
|
export const ModuleStructuralSymbols = [
|
||||||
{ i: symbolSet , t: UUID },
|
{ i: symbolSet , t: UUID },
|
||||||
|
|
@ -18,15 +13,11 @@ export const ModuleStructuralSymbols = [
|
||||||
{ i: symbolFunction , t: UUID },
|
{ i: symbolFunction , t: UUID },
|
||||||
];
|
];
|
||||||
|
|
||||||
const unaryTypeConstructor = fnType(_ => Type)(_ => Type);
|
|
||||||
|
|
||||||
const binaryTypeConstructor = fnType(_ => Type)(_ => unaryTypeConstructor);
|
|
||||||
|
|
||||||
export const ModuleTypeConstructors = [
|
export const ModuleTypeConstructors = [
|
||||||
{ i: setType , t: unaryTypeConstructor },
|
{ i: setType , t: mkType("Type -> Type") },
|
||||||
{ i: lsType , t: unaryTypeConstructor },
|
{ i: lsType , t: mkType("Type -> Type") },
|
||||||
{ i: prodType , t: binaryTypeConstructor },
|
{ i: prodType , t: mkType("Type -> Type -> Type") },
|
||||||
{ i: sumType , t: binaryTypeConstructor },
|
{ i: sumType , t: mkType("Type -> Type -> Type") },
|
||||||
{ i: dictType , t: binaryTypeConstructor },
|
{ i: dictType , t: mkType("Type -> Type -> Type") },
|
||||||
{ i: fnType , t: binaryTypeConstructor },
|
{ i: fnType , t: mkType("Type -> Type -> Type") },
|
||||||
];
|
];
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { inspect } from 'node:util';
|
import { inspect } from 'node:util';
|
||||||
import { symbolDict, symbolFunction, symbolList, symbolProduct, symbolSum, symbolSet } from '../structures/type_constructors.js';
|
import { symbolDict, symbolFunction, symbolList, symbolProduct, symbolSum } from '../structures/type_constructors.js';
|
||||||
|
import { symbolSet } from "../structures/type_constructors.js";
|
||||||
import { getHumanReadableName } from '../primitives/symbol.js';
|
import { getHumanReadableName } from '../primitives/symbol.js';
|
||||||
import { getSymbol } from '../primitives/type.js';
|
import { getSymbol } from '../primitives/type.js';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,19 @@
|
||||||
import createRBTree from "functional-red-black-tree";
|
import createRBTree from "functional-red-black-tree";
|
||||||
import { inspect } from "util";
|
import { inspect } from "util";
|
||||||
|
|
||||||
function defaultPrintf(depth, options, inspect) {
|
|
||||||
const entries = [];
|
|
||||||
this.tree.forEach((key, val) => { entries.push(`${inspect(key)} => ${inspect(val)}`); });
|
|
||||||
return `RBTree(${this.tree.length}) {${entries.join(', ')}}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class RBTreeWrapper {
|
export class RBTreeWrapper {
|
||||||
constructor(tree, printf = defaultPrintf) {
|
constructor(tree) {
|
||||||
this.tree = tree;
|
this.tree = tree;
|
||||||
this[inspect.custom] = printf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static new(compareFn) {
|
static new(compareFn) {
|
||||||
return new RBTreeWrapper(createRBTree(compareFn))
|
return new RBTreeWrapper(createRBTree(compareFn))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pretty print to console
|
||||||
|
[inspect.custom](depth, options, inspect) {
|
||||||
|
const entries = [];
|
||||||
|
this.tree.forEach((key, val) => { entries.push(`${inspect(key)} => ${inspect(val)}`); });
|
||||||
|
return `RBTree(${this.tree.length}) {${entries.join(', ')}}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,3 @@ export const memoize = callback => {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const indent = (multiline, n) => {
|
|
||||||
return multiline.split('\n').map(line => ' '.repeat(n)+line).join('\n');
|
|
||||||
}
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { compareTypes } from "../lib/compare/type.js";
|
||||||
import { makeGeneric, substitute, unify } from "../lib/generics/generics.js";
|
import { makeGeneric, substitute, unify } from "../lib/generics/generics.js";
|
||||||
import { Double, Int, Unit } from "../lib/primitives/primitive_types.js";
|
import { Double, Int, Unit } from "../lib/primitives/primitive_types.js";
|
||||||
import { UNBOUND_SYMBOLS } from "../lib/primitives/typevars.js";
|
import { UNBOUND_SYMBOLS } from "../lib/primitives/typevars.js";
|
||||||
import { fnType, lsType, prodType, sumType, setType } from "../lib/structures/type_constructors.types.js";
|
import { fnType, lsType, prodType, sumType, setType } from "../lib/structures/type_constructors.js";
|
||||||
import { prettyT } from "../lib/util/pretty.js";
|
import { prettyT } from "../lib/util/pretty.js";
|
||||||
|
|
||||||
// some recursive types:
|
// some recursive types:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue