add nominal types for 2D points
This commit is contained in:
parent
94efde3e65
commit
18b5e56ff0
6 changed files with 110 additions and 21 deletions
|
|
@ -15,6 +15,7 @@ export const makeGeneric = callback => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// From the given set of type variables, return only those that occur in the given type.
|
||||||
const occurring = (type, typeVars) => {
|
const occurring = (type, typeVars) => {
|
||||||
if (typeVars.has(type)) {
|
if (typeVars.has(type)) {
|
||||||
return new Set([type]);
|
return new Set([type]);
|
||||||
|
|
@ -36,7 +37,8 @@ const occurring = (type, typeVars) => {
|
||||||
|
|
||||||
// merge {i: [1], t: List_of_Int} ->
|
// merge {i: [1], t: List_of_Int} ->
|
||||||
|
|
||||||
|
// Thanks to Hans for pointing out that this algorithm exactly like "Unification" in Prolog:
|
||||||
|
// https://www.dai.ed.ac.uk/groups/ssp/bookpages/quickprolog/node12.html
|
||||||
export const matchGeneric = (
|
export const matchGeneric = (
|
||||||
{typeVars: formalTypeVars, type: formalType},
|
{typeVars: formalTypeVars, type: formalType},
|
||||||
{typeVars: actualTypeVars, type: actualType},
|
{typeVars: actualTypeVars, type: actualType},
|
||||||
|
|
|
||||||
57
lib/point.js
Normal file
57
lib/point.js
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { Function, Type } from "../metacircular.js";
|
||||||
|
import { Double } from "../primitives/symbols.js";
|
||||||
|
import { nominalType, NominalType } from "../structures/nominal_type.js";
|
||||||
|
import { fnType, prodType, typedFnType } from "../type_registry.js";
|
||||||
|
|
||||||
|
const PointCartesian2D = nominalType(
|
||||||
|
// just a unique number, to make sure that our type is only equal to itself
|
||||||
|
BigInt("0xBBAAD62B10EE21993BA690A732DA2A6875CE4B6F5E7139D5AEC9FD887F9D24A8"))
|
||||||
|
(prodType(Double, Double));
|
||||||
|
|
||||||
|
const PointPolar2D = nominalType(
|
||||||
|
// just a unique number, to make sure that our type is only equal to itself
|
||||||
|
BigInt("0x31CDAB4B3D84C4EB27D3C111FD7580E533268B72E05BD694F8B262913E018B72"))
|
||||||
|
(prodType(Double, Double));
|
||||||
|
|
||||||
|
export const cart2polar = ({left: x, right: y}) => {
|
||||||
|
const r = Math.sqrt(x*x + y*y);
|
||||||
|
const θ = Math.atan(y/x);
|
||||||
|
return {left: r, right: θ};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const polar2cart = ({left: r, right: θ}) => {
|
||||||
|
const x = r * Math.cos(θ);
|
||||||
|
const y = r * Math.sin(θ);
|
||||||
|
return {left: x, right: y};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const translate = dx => dy => ({left: x, right: y}) => {
|
||||||
|
return {left: x+dx, right: y+dy};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const rotate = dθ => ({left: r, right: θ}) => {
|
||||||
|
return {left: r, right: θ+dθ};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const scale = dr => ({left: r, right: θ}) => {
|
||||||
|
return {left: r+dr, right: θ};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ModulePoint = {l:[
|
||||||
|
{i: -1 , t: Double},
|
||||||
|
{i: 2 , t: Double},
|
||||||
|
{i: {left: 1, right: 2}, t: PointCartesian2D},
|
||||||
|
|
||||||
|
{i: PointCartesian2D , t: NominalType},
|
||||||
|
{i: PointPolar2D , t: NominalType},
|
||||||
|
|
||||||
|
...typedFnType(cart2polar, fnType => fnType({in: PointCartesian2D, out: PointPolar2D})),
|
||||||
|
|
||||||
|
...typedFnType(polar2cart, fnType => fnType({in: PointPolar2D, out: PointCartesian2D})),
|
||||||
|
|
||||||
|
...typedFnType(translate , fnType => fnType({in: Double, out: fnType({in: Double, out: fnType({in: PointCartesian2D, out: PointCartesian2D})})})),
|
||||||
|
|
||||||
|
...typedFnType(rotate, fnType => fnType({in: Double, out: fnType({in: PointPolar2D, out: PointPolar2D})})),
|
||||||
|
|
||||||
|
...typedFnType(scale, fnType => fnType({in: Double, out: fnType({in: PointPolar2D, out: PointPolar2D})})),
|
||||||
|
]};
|
||||||
40
main.js
40
main.js
|
|
@ -100,29 +100,31 @@ const ModuleValues = {l:[
|
||||||
{i: {variant: "L", value: 100n}, t: sumType(Int, Bool)},
|
{i: {variant: "L", value: 100n}, t: sumType(Int, Bool)},
|
||||||
]};
|
]};
|
||||||
|
|
||||||
|
import { select } from '@inquirer/prompts';
|
||||||
|
import { ModulePoint } from "./lib/point.js";
|
||||||
|
|
||||||
|
|
||||||
const ctx = new Context({l:[
|
const ctx = new Context({l:[
|
||||||
...ModuleMetaCircular.l,
|
// ...ModuleMetaCircular.l,
|
||||||
...ModuleTyped.l,
|
// ...ModuleTyped.l,
|
||||||
// ...ModuleConformable,
|
// // ...ModuleConformable,
|
||||||
// ...ModuleConformanceCheckConforms,
|
// // ...ModuleConformanceCheckConforms,
|
||||||
// ...ModuleNum,
|
// // ...ModuleNum,
|
||||||
// ...ModuleEq,
|
// // ...ModuleEq,
|
||||||
...ModuleBool.l,
|
// ...ModuleBool.l,
|
||||||
...ModuleInt.l,
|
// ...ModuleInt.l,
|
||||||
...ModuleDouble.l,
|
// ...ModuleDouble.l,
|
||||||
// ...ModuleSquare,
|
// // ...ModuleSquare,
|
||||||
// ...ModuleList,
|
// // ...ModuleList,
|
||||||
...makeIdFn(Int).l,
|
// ...makeIdFn(Int).l,
|
||||||
...makeSquare({i: mulInt, t: Int_to_Int_to_Int}).l,
|
// ...makeSquare({i: mulInt, t: Int_to_Int_to_Int}).l,
|
||||||
...makeSquare({i: mulDouble, t: Double_to_Double_to_Double}).l,
|
// ...makeSquare({i: mulDouble, t: Double_to_Double_to_Double}).l,
|
||||||
...ModuleList.l,
|
// ...ModuleList.l,
|
||||||
...ModuleValues.l,
|
// ...ModuleValues.l,
|
||||||
...ModuleModule.l,
|
// ...ModuleModule.l,
|
||||||
|
...ModulePoint.l,
|
||||||
]});
|
]});
|
||||||
|
|
||||||
import { input, select } from '@inquirer/prompts';
|
|
||||||
|
|
||||||
const makeChoice = ([i, t]) => {
|
const makeChoice = ([i, t]) => {
|
||||||
return {
|
return {
|
||||||
value: {i, t: t[0]},
|
value: {i, t: t[0]},
|
||||||
|
|
|
||||||
14
structures/nominal_type.js
Normal file
14
structures/nominal_type.js
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { Type } from "../metacircular.js";
|
||||||
|
import { Int } from "../primitives/symbols.js";
|
||||||
|
import { prodType } from "../type_registry.js";
|
||||||
|
import { makeProductType } from "./product.js";
|
||||||
|
|
||||||
|
export const NominalType = prodType(Int, Type);
|
||||||
|
|
||||||
|
export const ModuleNominalType = makeProductType(Int, Type);
|
||||||
|
|
||||||
|
export const nominalType = x => {
|
||||||
|
const result = ModuleNominalType.l[5].i(x); // dirty!!
|
||||||
|
result.__proto__.toString = () => "HEY";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// 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)
|
// 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.
|
// 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 { Function } from "./metacircular.js";
|
||||||
import { DefaultMap } from "./util.js";
|
import { DefaultMap } from "./util.js";
|
||||||
|
|
||||||
// Global store of function types:
|
// Global store of function types:
|
||||||
|
|
@ -18,6 +19,19 @@ export const fnType = ({in: inType, out: outType}) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const typedFnType = (instance, callback) => {
|
||||||
|
const fnTs = [];
|
||||||
|
const wrappedFnType = ({in: inType, out: outType}) => {
|
||||||
|
const fnT = fnType({in: inType, out: outType});
|
||||||
|
fnTs.push(fnT);
|
||||||
|
return fnT;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
{i: instance, t: callback(wrappedFnType)},
|
||||||
|
...fnTs.map(fnT => ({i: fnT, t: Function})),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
// Global store of list types:
|
// Global store of list types:
|
||||||
const listTypes = new Map();
|
const listTypes = new Map();
|
||||||
export const lsType = (elementType) => {
|
export const lsType = (elementType) => {
|
||||||
|
|
|
||||||
2
util.js
2
util.js
|
|
@ -45,5 +45,5 @@ export class DefaultMap {
|
||||||
import { inspect } from 'node:util';
|
import { inspect } from 'node:util';
|
||||||
|
|
||||||
export function pretty(obj) {
|
export function pretty(obj) {
|
||||||
return inspect(obj, {colors: true});
|
return inspect(obj, {colors: true, depth: null});
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue