lotta progress
This commit is contained in:
parent
29d20b2273
commit
bc91d9bf39
27 changed files with 317 additions and 475 deletions
|
|
@ -1,42 +1,6 @@
|
|||
import { DefaultMap } from "../util.js";
|
||||
|
||||
const symbolFunction = Symbol('Function');
|
||||
|
||||
// The registry ensures that we never accidentally create more than one JS object for the same function type.
|
||||
// It is a cheap workaround for JS lacking customizable hash-functions and equality-testing-functions.
|
||||
// This same pattern is repeated throughout the code for all non-nullary type constructors (list, sum, product, ...)
|
||||
const fnTypeRegistry = new DefaultMap(inType => new DefaultMap(outType => ({
|
||||
symbol: symbolFunction,
|
||||
params: [inType, outType],
|
||||
})));
|
||||
|
||||
// type constructor for function types
|
||||
export const fnType = inType => outType => fnTypeRegistry.getdefault(inType, true).getdefault(outType, true);
|
||||
|
||||
|
||||
// Wrapper around function below.
|
||||
export const typedFnType = (instance, callback) => {
|
||||
const [t, typesOfFns] = typedFnType2(callback);
|
||||
const res = [
|
||||
{ i: instance, t },
|
||||
...typesOfFns,
|
||||
];
|
||||
return res;
|
||||
};
|
||||
// Create a function type, and also create Type-links for the function type (being typed by Function) and for all the nested function types. Saves a lot of code writing.
|
||||
export const typedFnType2 = callback => {
|
||||
const fnTs = [];
|
||||
const wrappedFnType = ({ in: inType, out: outType }) => {
|
||||
const fnT = fnType({ in: inType, out: outType });
|
||||
fnTs.push(fnT);
|
||||
return fnT;
|
||||
};
|
||||
const t = callback(wrappedFnType); // force evaluation
|
||||
return [
|
||||
t,
|
||||
fnTs.map(fnT => ({ i: fnT, t: Function })),
|
||||
];
|
||||
};
|
||||
import { Type } from "../type.js";
|
||||
import { typedFnType } from "./types.js";
|
||||
import { fnType } from "./types.js";
|
||||
|
||||
|
||||
export const ModuleFunction = {l:[
|
||||
|
|
@ -48,4 +12,4 @@ export const ModuleFunction = {l:[
|
|||
/* out */ (Type)
|
||||
)
|
||||
),
|
||||
]};
|
||||
]};
|
||||
|
|
|
|||
|
|
@ -1,18 +1,8 @@
|
|||
import { typedFnType } from "./function.js";
|
||||
import { Type } from "../metacircular.js";
|
||||
import { Int } from "../primitives/symbols.js";
|
||||
import { DefaultMap } from "../util.js";
|
||||
import { typedFnType } from "./types.js";
|
||||
import { Type } from "../type.js";
|
||||
import { Int } from "../primitives/types.js";
|
||||
import { makeGeneric } from "../generics/generics.js";
|
||||
|
||||
const symbolList = Symbol('List');
|
||||
|
||||
const listTypeRegistry = new DefaultMap(elementType => ({
|
||||
symbol: symbolList,
|
||||
params: [elementType],
|
||||
}));
|
||||
|
||||
// type constructor
|
||||
export const lsType = elementType => listTypeRegistry.getdefault(elementType, true);
|
||||
import { lsType } from "./types.js";
|
||||
|
||||
// 'normal' implementation
|
||||
const emptyList = {l:[]};
|
||||
|
|
@ -22,30 +12,35 @@ const put = ls => i => elem => ({l: ls.l.with(Number(i), elem)});
|
|||
|
||||
export const ModuleList = {l:[
|
||||
// Type -> Type
|
||||
...typedFnType(lsType, fnType => fnType
|
||||
/* in */ (Type)
|
||||
/* out */ (Type)
|
||||
...typedFnType(lsType, fnType =>
|
||||
fnType
|
||||
/* in */ (Type)
|
||||
/* out */ (Type)
|
||||
),
|
||||
|
||||
// [a]
|
||||
{i: emptyList, t: makeGeneric(a => lsType(a))},
|
||||
|
||||
// [a] -> Int -> a
|
||||
...typedFnType(get, fnType => makeGeneric(a => fnType
|
||||
/* in */ (lsType(a))
|
||||
/* out */ (fnType
|
||||
/* in */ (Int)
|
||||
/* out */ (a)
|
||||
))),
|
||||
...typedFnType(get, fnType =>
|
||||
makeGeneric(a =>
|
||||
fnType
|
||||
/* in */ (lsType(a))
|
||||
/* out */ (fnType
|
||||
/* in */ (Int)
|
||||
/* out */ (a)
|
||||
))),
|
||||
|
||||
// [a] -> Int -> a -> [a]
|
||||
...typedFnType(put, fnType => makeGeneric(a => fnType
|
||||
/* in */ (lsType(a))
|
||||
/* out */ (fnType
|
||||
/* in */ (Int)
|
||||
/* out */ (fnType
|
||||
/* in */ (a)
|
||||
/* out */ (lsType(a))
|
||||
)
|
||||
))),
|
||||
...typedFnType(put, fnType =>
|
||||
makeGeneric(a =>
|
||||
fnType
|
||||
/* in */ (lsType(a))
|
||||
/* out */ (fnType
|
||||
/* in */ (Int)
|
||||
/* out */ (fnType
|
||||
/* in */ (a)
|
||||
/* out */ (lsType(a))
|
||||
)
|
||||
))),
|
||||
]};
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
import { makeListModule } from "../list.js";
|
||||
import { Typed } from "../../typed.js";
|
||||
import { lsType } from "../list.js";
|
||||
|
||||
// just an alias
|
||||
export const Module = lsType(Typed); // a Module is a list of Typeds
|
||||
|
||||
export const ModuleModule = makeListModule(Typed); // the module containing operations on Module
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
import { Char } from "../../primitives/symbols.js";
|
||||
import { lsType } from "../list.js";
|
||||
import { makeListModule } from "../list.js";
|
||||
|
||||
// just an alias
|
||||
export const String = lsType(Char);
|
||||
|
||||
export const ModuleString = makeListModule(Char);
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
import { Type } from "../metacircular.js";
|
||||
import { String } from "../structures/list_types/string.js";
|
||||
import { prodType } from "./product.js";
|
||||
import { makeProductType } from "./product.js";
|
||||
|
||||
export const NominalType = prodType(String, Type);
|
||||
|
||||
export const ModuleNominalType = makeProductType(String, Type);
|
||||
|
||||
export const nominalType = ModuleNominalType.l[5].i; // dirty!!
|
||||
|
|
@ -1,16 +1,7 @@
|
|||
import { makeGeneric } from "../generics/generics.js";
|
||||
import { Type } from "../metacircular.js";
|
||||
import { DefaultMap } from "../util.js";
|
||||
import { typedFnType } from "./function.js";
|
||||
|
||||
const symbolProduct = Symbol("Product");
|
||||
const productTypeRegistry = new DefaultMap(leftType => new DefaultMap(rightType => ({
|
||||
symbol: symbolProduct,
|
||||
params: [leftType, rightType],
|
||||
})));
|
||||
|
||||
// type constructor
|
||||
export const prodType = leftType => rightType => productTypeRegistry.getdefault(leftType, true).getdefault(rightType, true);
|
||||
import { Type } from "../type.js";
|
||||
import { typedFnType } from "./types.js";
|
||||
import { prodType } from "./types.js";
|
||||
|
||||
// In JS, all products are encoded in the same way:
|
||||
const constructor = left => right => ({left, right});
|
||||
|
|
@ -20,32 +11,39 @@ const getRight = product => product.right;
|
|||
export const ModuleProduct = {l: [
|
||||
// binary type constructor
|
||||
// Type -> Type -> Type
|
||||
...typedFnType(prodType, fnType => fnType
|
||||
(Type)
|
||||
(fnType
|
||||
...typedFnType(prodType, fnType =>
|
||||
fnType
|
||||
(Type)
|
||||
(Type)
|
||||
)
|
||||
(fnType
|
||||
(Type)
|
||||
(Type)
|
||||
)
|
||||
),
|
||||
|
||||
// a -> b -> (a, b)
|
||||
...typedFnType(constructor, fnType => makeGeneric((a, b) => fnType
|
||||
(a)
|
||||
(fnType
|
||||
(b)
|
||||
(prodType(a)(b))
|
||||
)
|
||||
)),
|
||||
...typedFnType(constructor, fnType =>
|
||||
makeGeneric((a, b) =>
|
||||
fnType
|
||||
(a)
|
||||
(fnType
|
||||
(b)
|
||||
(prodType(a)(b))
|
||||
)
|
||||
)),
|
||||
|
||||
// (a, b) -> a
|
||||
...typedFnType(getLeft, fnType => makeGeneric((a, b) => fnType
|
||||
(prodType(a)(b))
|
||||
(a)
|
||||
)),
|
||||
...typedFnType(getLeft, fnType =>
|
||||
makeGeneric((a, b) =>
|
||||
fnType
|
||||
(prodType(a)(b))
|
||||
(a)
|
||||
)),
|
||||
|
||||
// (a, b) -> b
|
||||
...typedFnType(getRight, fnType => makeGeneric((a, b) => fnType
|
||||
(prodType(a)(b))
|
||||
(b)
|
||||
)),
|
||||
...typedFnType(getRight, fnType =>
|
||||
makeGeneric((a, b) =>
|
||||
fnType
|
||||
(prodType(a)(b))
|
||||
(b)
|
||||
)),
|
||||
]};
|
||||
|
|
|
|||
|
|
@ -1,18 +1,8 @@
|
|||
import { prodType } from "./product.js";
|
||||
import { Type } from "../metacircular.js";
|
||||
import { DefaultMap } from "../util.js";
|
||||
import { typedFnType } from "./function.js";
|
||||
import { prodType } from "./types.js";
|
||||
import { Type } from "../type.js";
|
||||
import { typedFnType } from "./types.js";
|
||||
import { makeGeneric } from "../generics/generics.js";
|
||||
|
||||
const symbolSum = Symbol("Sum");
|
||||
|
||||
const sumTypeRegistry = new DefaultMap(leftType => new DefaultMap(rightType => ({
|
||||
symbol: symbolSum,
|
||||
params: [leftType, rightType],
|
||||
})));
|
||||
|
||||
// type constructor
|
||||
export const sumType = leftType => rightType => sumTypeRegistry.getdefault(leftType, true).getdefault(rightType, true);
|
||||
import { sumType } from "./types.js";
|
||||
|
||||
const constructorLeft = left => ({variant: "L", value: left });
|
||||
const constructorRight = right => ({variant: "R", value: right});
|
||||
|
|
@ -26,35 +16,42 @@ const match = sum => handlers => sum.variant === "L"
|
|||
export const ModuleSum = {l:[
|
||||
// binary type constructor
|
||||
// Type -> Type -> Type
|
||||
...typedFnType(sumType, fnType => fnType
|
||||
(Type)
|
||||
(fnType
|
||||
(Type)
|
||||
...typedFnType(sumType, fnType =>
|
||||
fnType
|
||||
(Type)
|
||||
(fnType
|
||||
(Type)
|
||||
(Type)
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// a -> a | b
|
||||
...typedFnType(constructorLeft, fnType => makeGeneric((a, b) => fnType
|
||||
(a)
|
||||
(sumType(a)(b))
|
||||
)),
|
||||
...typedFnType(constructorLeft, fnType =>
|
||||
makeGeneric((a, b) =>
|
||||
fnType
|
||||
(a)
|
||||
(sumType(a)(b))
|
||||
)),
|
||||
|
||||
// b -> a | b
|
||||
...typedFnType(constructorRight, fnType => makeGeneric((a, b) => fnType
|
||||
(b)
|
||||
(sumType(a)(b))
|
||||
)),
|
||||
...typedFnType(constructorRight, fnType =>
|
||||
makeGeneric((a, b) =>
|
||||
fnType
|
||||
(b)
|
||||
(sumType(a)(b))
|
||||
)),
|
||||
|
||||
// a | b -> (a -> c, b-> c) -> c
|
||||
...typedFnType(match, fnType => makeGeneric((a, b, c) => fnType
|
||||
(sumType(a)(b))
|
||||
(fnType
|
||||
(prodType
|
||||
(fnType(a)(c))
|
||||
(fnType(b)(c))
|
||||
)
|
||||
(c)
|
||||
)
|
||||
)),
|
||||
...typedFnType(match, fnType =>
|
||||
makeGeneric((a, b, c) =>
|
||||
fnType
|
||||
(sumType(a)(b))
|
||||
(fnType
|
||||
(prodType
|
||||
(fnType(a)(c))
|
||||
(fnType(b)(c))
|
||||
)
|
||||
(c)
|
||||
)
|
||||
)),
|
||||
]};
|
||||
|
|
|
|||
74
structures/types.js
Normal file
74
structures/types.js
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
// to break up dependency cycles, type constructors are defined in their own JS module
|
||||
|
||||
import { DefaultMap } from "../util.js";
|
||||
|
||||
|
||||
// Function type
|
||||
|
||||
// The registry ensures that we never accidentally create more than one JS object for the same function type.
|
||||
// It is a cheap workaround for JS lacking customizable hash-functions and equality-testing-functions.
|
||||
// This same pattern is repeated throughout the code for all non-nullary type constructors (list, sum, product, ...)
|
||||
export const symbolFunction = Symbol('Function');
|
||||
const fnTypeRegistry = new DefaultMap(inType => new DefaultMap(outType => ({
|
||||
symbol: symbolFunction,
|
||||
params: [inType, outType],
|
||||
})));
|
||||
// type constructor
|
||||
export const fnType = inType => outType => fnTypeRegistry.getdefault(inType, true).getdefault(outType, true);
|
||||
|
||||
// Convenience function. Wrapper around function below.
|
||||
export const typedFnType = (instance, callback) => {
|
||||
const [t, typesOfFns] = typedFnType2(callback);
|
||||
const res = [
|
||||
{ i: instance, t },
|
||||
...typesOfFns,
|
||||
];
|
||||
return res;
|
||||
};
|
||||
// Convenience function. Creates a function type, and also create Type-links for the function type (being typed by Function) and for all the nested function types. Saves a lot of code writing.
|
||||
export const typedFnType2 = callback => {
|
||||
const fnTs = [];
|
||||
const wrappedFnType = inType => outType => {
|
||||
const fnT = fnType(inType)(outType);
|
||||
fnTs.push(fnT);
|
||||
return fnT;
|
||||
};
|
||||
const t = callback(wrappedFnType); // force evaluation
|
||||
return [
|
||||
t,
|
||||
fnTs.map(fnT => ({ i: fnT, t: Function })),
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
// Sum type
|
||||
|
||||
const symbolSum = Symbol("Sum");
|
||||
const sumTypeRegistry = new DefaultMap(leftType => new DefaultMap(rightType => ({
|
||||
symbol: symbolSum,
|
||||
params: [leftType, rightType],
|
||||
})));
|
||||
// type constructor
|
||||
export const sumType = leftType => rightType => sumTypeRegistry.getdefault(leftType, true).getdefault(rightType, true);
|
||||
|
||||
|
||||
// Product type
|
||||
|
||||
const symbolProduct = Symbol("Product");
|
||||
const productTypeRegistry = new DefaultMap(leftType => new DefaultMap(rightType => ({
|
||||
symbol: symbolProduct,
|
||||
params: [leftType, rightType],
|
||||
})));
|
||||
// type constructor
|
||||
export const prodType = leftType => rightType => productTypeRegistry.getdefault(leftType, true).getdefault(rightType, true);
|
||||
|
||||
|
||||
// List type
|
||||
|
||||
const symbolList = Symbol('List');
|
||||
const listTypeRegistry = new DefaultMap(elementType => ({
|
||||
symbol: symbolList,
|
||||
params: [elementType],
|
||||
}));
|
||||
// type constructor
|
||||
export const lsType = elementType => listTypeRegistry.getdefault(elementType, true);
|
||||
Loading…
Add table
Add a link
Reference in a new issue