refactor code: move everything from type_registry to "most appropriate" modules
This commit is contained in:
parent
4ca60784aa
commit
5283be608b
22 changed files with 160 additions and 164 deletions
|
|
@ -1,6 +1,21 @@
|
|||
import { fnType, lsType } from "../type_registry.js";
|
||||
import { lsType } from "../structures/list_common.js";
|
||||
import { fnType } from "../metacircular.js";
|
||||
import { deepEqual, pretty } from "../util.js";
|
||||
|
||||
const genericTypeRegistry = new DefaultMap(underlyingType => ({generic: underlyingType}));
|
||||
|
||||
// type constructor for generic kinds,
|
||||
// for instance:
|
||||
// a -> a -> Bool
|
||||
// is typed by
|
||||
// genericType(Function)
|
||||
export const genericType = underlyingType => genericTypeRegistry.getdefault(underlyingType, true);
|
||||
|
||||
// constructor for generic types
|
||||
// for instance, the type:
|
||||
// a -> a -> Bool
|
||||
// is created by
|
||||
// makeGeneric(a => fnType({in: a, out: fnType({in: a, out: Bool})}))
|
||||
export const makeGeneric = callback => {
|
||||
// type variables to make available:
|
||||
const a = Symbol('a');
|
||||
|
|
@ -32,14 +47,11 @@ const occurring = (type, typeVars) => {
|
|||
return new Set();
|
||||
}
|
||||
|
||||
// merge_int(1, 2) => conflict(1,2)
|
||||
// merge_list_of_int([1], [2]) => [conflict(1,2)]
|
||||
// Currently very ad-hoc.
|
||||
|
||||
// merge {i: [1], t: List_of_Int} ->
|
||||
|
||||
// Thanks to Hans for pointing out that this algorithm exactly like "Unification" in Prolog:
|
||||
// Thanks to Hans for pointing out that this algorithm exactly like "Unification" in Prolog (hence the function name):
|
||||
// https://www.dai.ed.ac.uk/groups/ssp/bookpages/quickprolog/node12.html
|
||||
export const matchGeneric = (
|
||||
export const unify = (
|
||||
{typeVars: formalTypeVars, type: formalType},
|
||||
{typeVars: actualTypeVars, type: actualType},
|
||||
) => {
|
||||
|
|
@ -71,8 +83,8 @@ export const matchGeneric = (
|
|||
}
|
||||
else {
|
||||
// both are function type
|
||||
const inType = matchGeneric({typeVars: formalTypeVars, type: formalType.in}, {typeVars: actualTypeVars, type: actualType.in});
|
||||
const outType = matchGeneric({typeVars: formalTypeVars, type: formalType.out}, {typeVars: actualTypeVars, type: actualType.out});
|
||||
const inType = unify({typeVars: formalTypeVars, type: formalType.in}, {typeVars: actualTypeVars, type: actualType.in});
|
||||
const outType = unify({typeVars: formalTypeVars, type: formalType.out}, {typeVars: actualTypeVars, type: actualType.out});
|
||||
// check for conflicts between 'in' and 'out' subsitutions
|
||||
for (const [typeVar, actual] of inType.substitutions) {
|
||||
if (outType.substitutions.has(typeVar)) {
|
||||
|
|
@ -104,7 +116,7 @@ export const matchGeneric = (
|
|||
}
|
||||
else {
|
||||
// both are list type
|
||||
const elementType = matchGeneric(
|
||||
const elementType = unify(
|
||||
{typeVars: formalTypeVars, type: formalType.listOf},
|
||||
{typeVars: actualTypeVars, type: actualType.listOf});
|
||||
return {
|
||||
|
|
@ -116,12 +128,16 @@ export const matchGeneric = (
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (formalType.numDict !== undefined) {
|
||||
|
||||
}
|
||||
throw new Error("i don't know what to do :(")
|
||||
};
|
||||
|
||||
export const matchConcrete = ({typeVars, type: formalType}, actualType) => {
|
||||
return matchGeneric({typeVars, type: formalType}, {typeVars: new Set(), type: actualType});
|
||||
};
|
||||
// export const matchConcrete = ({typeVars, type: formalType}, actualType) => {
|
||||
// return unify({typeVars, type: formalType}, {typeVars: new Set(), type: actualType});
|
||||
// };
|
||||
|
||||
export const substitute = (type, substitutions) => {
|
||||
if (substitutions.has(type)) {
|
||||
|
|
@ -142,7 +158,7 @@ export const substitute = (type, substitutions) => {
|
|||
}
|
||||
|
||||
export const assign = (genFnType, paramType) => {
|
||||
const matchedInType = matchGeneric({
|
||||
const matchedInType = unify({
|
||||
typeVars: genFnType.typeVars,
|
||||
type: genFnType.type.in,
|
||||
}, paramType);
|
||||
|
|
|
|||
|
|
@ -1,20 +1,21 @@
|
|||
import { Bool, Int } from "../primitives/symbols.js";
|
||||
import { fnType, lsType } from "../type_registry.js";
|
||||
import { assign, makeGeneric, matchConcrete, matchGeneric } from "./generics.js";
|
||||
import { lsType } from "../structures/list_common.js";
|
||||
import { fnType } from "../metacircular.js";
|
||||
import { assign, makeGeneric, unify } from "./generics.js";
|
||||
|
||||
// a -> Int
|
||||
const a_to_Int = makeGeneric(a => fnType({in: a, out: Int}));
|
||||
// Bool -> Int
|
||||
const Bool_to_Int = fnType({in: lsType(Bool), out: Int});
|
||||
const Bool_to_Int = makeGeneric(() => fnType({in: lsType(Bool), out: Int}));
|
||||
// should be: Bool -> Int
|
||||
console.log(matchConcrete(a_to_Int, Bool_to_Int));
|
||||
console.log(unify(a_to_Int, Bool_to_Int));
|
||||
|
||||
// (a -> a) -> b
|
||||
const fnType2 = makeGeneric((a,b) => fnType({in: fnType({in: a, out: a}), out: b}));
|
||||
// (Bool -> Bool) -> a
|
||||
const fnType3 = makeGeneric(a => fnType({in: fnType({in: Bool, out: Bool}), out: a}));
|
||||
// should be: (Bool -> Bool) -> a
|
||||
console.log(matchGeneric(fnType2, fnType3));
|
||||
console.log(unify(fnType2, fnType3));
|
||||
|
||||
// (a -> b) -> [a] -> [b]
|
||||
const mapFnType = makeGeneric((a,b) =>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { fnType } from "../type_registry.js";
|
||||
import { fnType } from "../metacircular.js";
|
||||
import {Function} from "../metacircular.js";
|
||||
|
||||
// import {Typed} from "../typed.js";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { Double } from "../primitives/symbols.js";
|
||||
import { nominalType, NominalType } from "../structures/nominal_type.js";
|
||||
import { makeProductType } from "../structures/product.js";
|
||||
import { prodType, typedFnType } from "../type_registry.js";
|
||||
import { typedFnType } from "../metacircular.js";
|
||||
import { prodType } from "../structures/product.js";
|
||||
|
||||
const PointCartesian2D = nominalType(
|
||||
"PointCartesian2D")
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import {Function, getIn, getOut} from "../metacircular.js";
|
|||
import {Module} from "../structures/list_types/module.js";
|
||||
import { deepEqual } from "../util.js";
|
||||
import { Typed } from "../typed.js";
|
||||
import { fnType } from "../type_registry.js";
|
||||
import { fnType } from "../metacircular.js";
|
||||
|
||||
// import {Num, NumDict, getType, getMul} from "../typeclasses/num.js";
|
||||
|
||||
|
|
|
|||
4
main.js
4
main.js
|
|
@ -13,7 +13,9 @@ import {Int, Bool, Double, Byte} from "./primitives/symbols.js";
|
|||
import { makeListModule } from "./structures/list_common.js";
|
||||
import { makeProductType } from "./structures/product.js";
|
||||
import { makeSumType } from "./structures/sum.js";
|
||||
import { lsType, prodType, sumType } from "./type_registry.js";
|
||||
import { sumType } from "./structures/sum.js";
|
||||
import { prodType } from "./structures/product.js";
|
||||
import { lsType } from "./structures/list_common.js";
|
||||
|
||||
class Context {
|
||||
constructor(mod) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,12 @@
|
|||
import { fnType } from "./type_registry.js";
|
||||
import { DefaultMap } from "./util.js";
|
||||
|
||||
// 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 => ({ in: inType, out: outType })));
|
||||
|
||||
// type constructor for function types
|
||||
export const fnType = ({ in: inType, out: outType }) => fnTypeRegistry.getdefault(inType, true).getdefault(outType, true);
|
||||
|
||||
export const Type = Symbol('Type');
|
||||
export const Function = Symbol('Function');
|
||||
|
|
@ -29,3 +37,30 @@ export const ModuleMetaCircular = {l:[
|
|||
{i: getIn , t: fnType({in: Function, out: Type})},
|
||||
{i: getOut, t: fnType({in: Function, out: Type})},
|
||||
]};
|
||||
|
||||
|
||||
// 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 }) => {
|
||||
console.log('wrappedFnType called');
|
||||
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 })),
|
||||
];
|
||||
};
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { fnType } from "../type_registry.js";
|
||||
import { fnType } from "../metacircular.js";
|
||||
import {Type, Function} from "../metacircular.js";
|
||||
import {Bool} from "./symbols.js";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { fnType } from "../type_registry.js";
|
||||
import { fnType } from "../metacircular.js";
|
||||
import {Type, Function} from "../metacircular.js";
|
||||
|
||||
import {Bool, Double} from "./symbols.js";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { fnType } from "../type_registry.js";
|
||||
import { fnType } from "../metacircular.js";
|
||||
import {Type, Function} from "../metacircular.js";
|
||||
|
||||
import {Bool, Int} from "./symbols.js";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { fnType, lsType } from "../type_registry.js";
|
||||
import { lsType } from "./list_common.js";
|
||||
import { fnType } from "../metacircular.js";
|
||||
import {Type, Function} from "../metacircular.js";
|
||||
import { makeListModule } from "./list_common.js";
|
||||
import { Module } from "./list_types/module.js";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
import { fnType, lsType } from "../type_registry.js";
|
||||
import { fnType } from "../metacircular.js";
|
||||
import {Type, Function} from "../metacircular.js";
|
||||
import {Int, Byte} from "../primitives/symbols.js";
|
||||
import { DefaultMap } from "../util.js";
|
||||
|
||||
const listTypeRegistry = new DefaultMap(elementType => ({ listOf: elementType }));
|
||||
|
||||
// type constructor
|
||||
export const lsType = elementType => listTypeRegistry.getdefault(elementType, true);
|
||||
|
||||
// 'normal' implementation
|
||||
const emptyList = {l:[]};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { makeListModule } from "../list_common.js";
|
||||
import { Typed } from "../../typed.js";
|
||||
import { lsType } from "../../type_registry.js";
|
||||
import { lsType } from "../list_common.js";
|
||||
|
||||
export const Module = lsType(Typed); // a Module is a list of Typeds
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Char } from "../../primitives/symbols.js";
|
||||
import { lsType } from "../../type_registry.js";
|
||||
import { lsType } from "../list_common.js";
|
||||
import { makeListModule } from "../list_common.js";
|
||||
|
||||
export const String = lsType(Char);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Type } from "../metacircular.js";
|
||||
import { String } from "../structures/list_types/string.js";
|
||||
import { prodType } from "../type_registry.js";
|
||||
import { prodType } from "./product.js";
|
||||
import { makeProductType } from "./product.js";
|
||||
|
||||
export const NominalType = prodType(String, Type);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
import { fnType, prodType } from "../type_registry.js";
|
||||
import { fnType } from "../metacircular.js";
|
||||
import { Function, Type } from "../metacircular.js";
|
||||
import { DefaultMap } from "../util.js";
|
||||
|
||||
const productTypeRegistry = new DefaultMap(leftType => new DefaultMap(rightType => ({ operator: "product", leftType, rightType })));
|
||||
|
||||
// type constructor
|
||||
export const prodType = (leftType, rightType) => productTypeRegistry.getdefault(leftType, true).getdefault(rightType, true);
|
||||
|
||||
// In JS, all products are encoded in the same way:
|
||||
const constructor = left => right => ({left, right});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
import { fnType, prodType, sumType } from "../type_registry.js";
|
||||
import { sumType } from "../type_registry.js";
|
||||
import { prodType } from "./product.js";
|
||||
import { fnType } from "../metacircular.js";
|
||||
import { Function, Type } from "../metacircular.js";
|
||||
import { Module } from "./list_types/module.js";
|
||||
|
||||
const sumTypeRegistry = new DefaultMap(leftType => new DefaultMap(rightType => ({ operator: "sum", leftType, rightType })));
|
||||
|
||||
// type constructor
|
||||
export const sumType = (leftType, rightType) => sumTypeRegistry.getdefault(leftType, true).getdefault(rightType, true);
|
||||
|
||||
const constructorLeft = left => ({variant: "L", value: left });
|
||||
const constructorRight = right => ({variant: "R", value: right});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
// This module ensures that we never accidentally create more than one JS object for the same type twice.
|
||||
// We do so by creating (nested) DefaultMap(s) for all non-nullary type constructors
|
||||
// It is a cheap workaround for JS lacking customizable hash-functions and equality-testing-functions.
|
||||
|
||||
import { Function } from "./metacircular.js";
|
||||
import { DefaultMap } from "./util.js";
|
||||
|
||||
|
||||
const listTypeRegistry = new DefaultMap(elementType => ({listOf: elementType}));
|
||||
const genericTypeRegistry = new DefaultMap(underlyingType => ({generic: underlyingType}));
|
||||
const fnTypeRegistry = new DefaultMap(inType => new DefaultMap(outType => ({in: inType, out: outType})));
|
||||
const productTypeRegistry = new DefaultMap(leftType => new DefaultMap(rightType => ({operator: "product", leftType, rightType})));
|
||||
const sumTypeRegistry = new DefaultMap(leftType => new DefaultMap(rightType => ({operator: "sum", leftType, rightType})));
|
||||
|
||||
|
||||
export const lsType = listTypeRegistry.getdefault.bind(listTypeRegistry);
|
||||
export const genericType = genericTypeRegistry.getdefault.bind(genericTypeRegistry);
|
||||
export const fnType = ({in: inType, out: outType}) => fnTypeRegistry.getdefault(inType, true).getdefault(outType, true);
|
||||
export const sumType = (leftType, rightType) => sumTypeRegistry.getdefault(leftType, true).getdefault(rightType, true);
|
||||
export const prodType = (leftType, rightType) => productTypeRegistry.getdefault(leftType, true).getdefault(rightType, 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}) => {
|
||||
console.log('wrappedFnType called')
|
||||
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})),
|
||||
];
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
// import {Type, Function, makeTypedFnInOut, fnOut} from "../metacircular.js";
|
||||
// import {Bool} from "../primitives/symbols.js";
|
||||
|
||||
// export const Conformable = Symbol('Conformable');
|
||||
// export const conformanceCheck = Symbol('conformanceCheck');
|
||||
|
||||
// export const ModuleConformable = [
|
||||
// {i: Conformable , t: Type},
|
||||
// {i: conformanceCheck, t: Function},
|
||||
|
||||
// // Note: outType is just 'Type', we cannot use Bool because a function that has type 'conformanceCheck' will have outType Bool, therefore conformanceCheck must return the type of Bool, which is Type.
|
||||
// ...makeTypedFnInOut({f: conformanceCheck, inType: Conformable, outType: Type}),
|
||||
// ];
|
||||
|
||||
|
||||
|
||||
// ////////////////////////////////////////////////////////
|
||||
// // Conformance check functions are themselves conformance checkable
|
||||
// // This is because we want to restrict their return type to Bool
|
||||
|
||||
// const conformanceCheckIsConform = fn => {
|
||||
// return fnOut(fn) === Bool;
|
||||
// };
|
||||
|
||||
// const conformanceCheckIsConformFn = {name: "isConform", inType: conformanceCheck, outType: Bool, fn: conformanceCheckIsConform};
|
||||
|
||||
|
||||
// export const ModuleConformanceCheckConforms = [
|
||||
// // instances of conformanceCheck (= 'isConform'-functions) are themselves conformance checkable
|
||||
// {i: conformanceCheck, t: Conformable},
|
||||
// {i: conformanceCheckIsConformFn, t: conformanceCheck},
|
||||
// {i: conformanceCheckIsConformFn, t: Function},
|
||||
// ];
|
||||
|
|
@ -1,52 +1,54 @@
|
|||
// import {Type, Function, makeTypedFnInOut, fnIn, fnOut} from "../metacircular.js";
|
||||
// import {Conformable, conformanceCheck} from "./conformable.js";
|
||||
// import {Bool} from "../primitives/symbols.js";
|
||||
// import {deepEqual} from "../util.js";
|
||||
import { makeGeneric } from "../generics/generics";
|
||||
import { addDouble, mulDouble } from "../primitives/double";
|
||||
import { addInt, mulInt } from "../primitives/int";
|
||||
import { typedFnType, typedFnType2 } from "../metacircular";
|
||||
|
||||
// export const Num = Symbol('Num');
|
||||
// export const NumDict = Symbol('NumDict');
|
||||
// // export const addType = Symbol('addType');
|
||||
// // export const addBoundType = Symbol('addBoundType');
|
||||
// // export const mulType = Symbol('mulType');
|
||||
// // export const mulBoundType = Symbol('mulBoundType');
|
||||
const numDictTypeRegistry = new DefaultMap(a => ({numDict: a}));
|
||||
export const numDictType = a => numDictTypeRegistry.getdefault(a, true);
|
||||
|
||||
// // export const getType = numDict => numDict.type;
|
||||
export const getAdd = numDict => numDict.add;
|
||||
export const getMul = numDict => numDict.mul;
|
||||
|
||||
// export const getAdd = numDict => numDict.add;
|
||||
// export const getMul = numDict => numDict.mul;
|
||||
// getAdd and getMul have same (generic) type:
|
||||
const [getAddMulFnType, typesOfFns] = typedFnType2(fnType =>
|
||||
makeGeneric(a => fnType({
|
||||
in: numDictType(a),
|
||||
out: fnType({
|
||||
in: a,
|
||||
out: fnType({in: a, out: a}),
|
||||
}),
|
||||
})));
|
||||
|
||||
// // const addOrMulIsConform = fn => {
|
||||
// // // function signature must be: a -> a -> a
|
||||
// // const i0 = fnIn(fn);
|
||||
// // const o0 = fnOut(fn);
|
||||
// // const i1 = fnIn(o0);
|
||||
// // const o1 = fnOut(o0);
|
||||
// // return deepEqual(i0, i1) && deepEqual(i1, o1);
|
||||
// // };
|
||||
export const ModuleNum = {l:[
|
||||
...typedFnType(numDictType, fnType => fnType({in: Type, out: Type})),
|
||||
|
||||
// // const addIsConform = {name: "isConform", inType: addType, outType: Bool, fn: addOrMulIsConform};
|
||||
// // const mulIsConform = {name: "isConform", inType: mulType, outType: Bool, fn: addOrMulIsConform};
|
||||
{i: getAdd, t: getAddMulFnType},
|
||||
{i: getMul, t: getAddMulFnType},
|
||||
|
||||
// export const ModuleNum = [
|
||||
// {i: Num, t: Type},
|
||||
// {i: NumDict, t: Type},
|
||||
// {i: addType, t: Type},
|
||||
// {i: addBoundType, t: Type},
|
||||
// {i: mulType, t: Type},
|
||||
// {i: mulBoundType, t: Type},
|
||||
// {i: {name: "getType", inType: NumDict, outType: Num, fn: getType}, t: Function},
|
||||
// {i: {name: "getAdd", inType: NumDict, outType: addType, fn: getAdd }, t: Function},
|
||||
// {i: {name: "getMul", inType: NumDict, outType: mulType, fn: getMul }, t: Function},
|
||||
// ...makeTypedFnInOut({f: addType , inType: Num, outType: addBoundType}),
|
||||
// ...makeTypedFnInOut({f: addBoundType, inType: Num, outType: Num }),
|
||||
// ...makeTypedFnInOut({f: mulType , inType: Num, outType: mulBoundType}),
|
||||
// ...makeTypedFnInOut({f: mulBoundType, inType: Num, outType: Num }),
|
||||
...typesOfFns,
|
||||
]};
|
||||
|
||||
// // conformance checking type class
|
||||
// {i: addType, t: Conformable},
|
||||
// {i: mulType, t: Conformable},
|
||||
// {i: addIsConform, t: Function},
|
||||
// {i: addIsConform, t: conformanceCheck},
|
||||
// {i: mulIsConform, t: Function},
|
||||
// {i: mulIsConform, t: conformanceCheck},
|
||||
// ];
|
||||
|
||||
const IntNumDict = {
|
||||
add: addInt,
|
||||
mul: mulInt,
|
||||
};
|
||||
|
||||
const DoubleNumDict = {
|
||||
add: addDouble,
|
||||
mul: mulDouble,
|
||||
}
|
||||
|
||||
export const ModuleNumInstances = {l:[
|
||||
{i: IntNumDict , t: NumDict},
|
||||
{i: DoubleNumDict, t: NumDict},
|
||||
]};
|
||||
|
||||
// mapping from type to type class implementation
|
||||
// in Haskell, such a mapping is global (for the entire application being compiled), and every type can implement every type class at most once.
|
||||
// in Lean, such mappings can be local, and there can be multiple implementations per (type, type class).
|
||||
// We have to follow Lean's approach, because in DOPE, there is no such thing as a "global scope". Every dependency is explicit, and type class resolution is just a function that always depends on a specific mapping:
|
||||
export const NumInstances = new Map([
|
||||
[Int , IntNumDict ],
|
||||
[Double, DoubleNumDict],
|
||||
]);
|
||||
2
typed.js
2
typed.js
|
|
@ -1,4 +1,4 @@
|
|||
import { fnType } from "./type_registry.js";
|
||||
import { fnType } from "./metacircular.js";
|
||||
import {Type, Function} from "./metacircular.js";
|
||||
|
||||
export const Typed = Symbol('Typed');
|
||||
|
|
|
|||
1
util.js
1
util.js
|
|
@ -22,7 +22,6 @@ export function deepEqual(a, b) {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
export class DefaultMap {
|
||||
constructor(defaultValue, ...rest) {
|
||||
this.defaultValue = defaultValue;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue