diff --git a/compare/registry.js b/compare/registry.js index 9852e01..dc2342e 100644 --- a/compare/registry.js +++ b/compare/registry.js @@ -1,3 +1,4 @@ +import { getInst, getType } from "../primitives/dynamic.js"; import { SymbolBool, SymbolChar, SymbolDouble, SymbolInt, SymbolType, SymbolUnit } from "../primitives/types.js"; import { symbolList, symbolProduct, symbolSet, symbolSum } from "../structures/types.js"; import { compareBools, compareNumbers, compareStrings, compareUnits } from "./primitives.js"; @@ -17,11 +18,15 @@ const typeSymbolToCmp = new Map([ [symbolProduct, compareProducts], [symbolSum , compareSums], [symbolSet , compareSets], -]) +]); export const makeCompareFn = type => { return type.params.reduce( (acc, cur) => acc(makeCompareFn(cur)), typeSymbolToCmp.get(type.symbol) ); -} +}; + +export const compareDynamic = x => y => + compareTypes(getType(x))(getType(y)) + || makeCompareFn(getType(x))(getInst(x))(getInst(y)); diff --git a/compare/structures.js b/compare/structures.js index d1f669d..dbb9a9f 100644 --- a/compare/structures.js +++ b/compare/structures.js @@ -3,7 +3,7 @@ import { compareNumbers } from "./primitives.js" import { get, length as lengthLs } from "../structures/list.js"; import { read, length as lengthSet } from "../structures/set.js"; -import { constructorProduct, getLeft, getRight } from "../structures/product.js"; +import { newProduct, getLeft, getRight } from "../structures/product.js"; import { match } from "../structures/sum.js"; // (a -> a -> Int) -> [a] -> [a] -> Int @@ -28,12 +28,12 @@ export const compareProducts = compareLeft => compareRight => x => y => { // (a -> a -> Int) -> (b -> b -> Int) -> (a | b) -> (a | b) -> Int export const compareSums = compareLeft => compareRight => x => y => { - return match(x)(constructorProduct - (leftValueX => match(y)(constructorProduct + return match(x)(newProduct + (leftValueX => match(y)(newProduct (leftValueY => compareLeft(leftValueX)(leftValueY)) ((rightValueY) => -1) // x is 'left' and y is 'right' => x < y )) - (rightValueX => match(y)(constructorProduct + (rightValueX => match(y)(newProduct (leftValueY => 1) // x is 'right' and y is 'left' => x > y (rightValueY => compareRight(rightValueX)(rightValueY)) )) diff --git a/examples/enum.js b/examples/enum.js index ff5e16c..c6231e2 100644 --- a/examples/enum.js +++ b/examples/enum.js @@ -2,13 +2,13 @@ import { makeCompareFn } from "../compare/registry.js"; import { Int, Unit } from "../primitives/types.js"; import { unit } from "../primitives/unit.js"; import { enumType, makeConstructors, makeMatchFn } from "../structures/enum.js"; -import { constructorProduct } from "../structures/product.js"; +import { newProduct } from "../structures/product.js"; import { lsType, prettyT } from "../structures/types.js"; const variants = [ - constructorProduct("price")(Int), - constructorProduct("prices")(lsType(Int)), - constructorProduct("not_found")(Unit), + newProduct("price")(Int), + newProduct("prices")(lsType(Int)), + newProduct("not_found")(Unit), ]; const myEnumType = enumType(variants); diff --git a/examples/int_or_bool.js b/examples/int_or_bool.js index 0a1e1f0..9b29e79 100644 --- a/examples/int_or_bool.js +++ b/examples/int_or_bool.js @@ -1,6 +1,6 @@ import { assign, makeGeneric, unify } from "../generics/generics.js"; import { Bool, Int } from "../primitives/types.js"; -import { constructorLeft, constructorRight, match } from "../structures/sum.js"; +import { newLeft, newRight, match } from "../structures/sum.js"; import { fnType, sumType } from "../structures/types.js"; import { pretty } from '../util/pretty.js'; @@ -33,7 +33,7 @@ console.log(assign( makeGeneric(() => IntOrBool), )); -console.log("calling constructorLeft with Int:"); +console.log("calling newLeft with Int:"); const typeAtCallSite = assign( makeGeneric((a, b) => fnType @@ -51,10 +51,10 @@ console.log(pretty(assign( ))); console.log("valid function calls:"); -console.log(cipFunction(constructorLeft(5))); -console.log(cipFunction(constructorLeft(7))); -console.log(cipFunction(constructorRight(true))); +console.log(cipFunction(newLeft(5))); +console.log(cipFunction(newLeft(7))); +console.log(cipFunction(newRight(true))); console.log("invalid function calls:"); console.log(cipFunction(5)); -console.log(cipFunction(constructorLeft("abc"))); +console.log(cipFunction(newLeft("abc"))); diff --git a/examples/main.js b/examples/prompt.js similarity index 100% rename from examples/main.js rename to examples/prompt.js diff --git a/lib/point_structural.js b/lib/point_structural.js index c162c74..cf866a0 100644 --- a/lib/point_structural.js +++ b/lib/point_structural.js @@ -1,17 +1,17 @@ import { prettyT, typedFnType } from "../structures/types.js" import { Double } from "../primitives/types.js"; import { makeConstructor, makeConstructorType, makeGetters, makeGettersTypes, structType } from "../structures/struct.js"; -import { constructorProduct } from "../structures/product.js"; +import { newProduct } from "../structures/product.js"; import { makeTypeConstructor } from "../type_constructor.js"; const cartFields = [ - constructorProduct("x")(Double), - constructorProduct("y")(Double), + newProduct("x")(Double), + newProduct("y")(Double), ]; const polarFields = [ - constructorProduct("r")(Double), - constructorProduct("θ")(Double), + newProduct("r")(Double), + newProduct("θ")(Double), ]; // Nominal types: diff --git a/primitives/dynamic.js b/primitives/dynamic.js new file mode 100644 index 0000000..769470b --- /dev/null +++ b/primitives/dynamic.js @@ -0,0 +1,19 @@ +import { typedFnType } from "../structures/types.js"; +import { Any, Type } from "./types.js"; +import { makeTypeConstructor } from "../type_constructor.js"; + +// A type-link, connecting a value to its Type. +export const symbolDynamic = Symbol('Dynamic'); +export const Dynamic = makeTypeConstructor(symbolDynamic)(0); + +export const getInst = lnk => lnk.i; +export const getType = lnk => lnk.t; + +export const ModuleDynamic = {l:[ + {i: Dynamic, t: Type}, + {i: Any , t: Type}, + + ...typedFnType(getInst, fnType => fnType(Dynamic)(Any)), + ...typedFnType(getType, fnType => fnType(Dynamic)(Any)), +]}; + diff --git a/primitives/generic_type.js b/primitives/generic_type.js index c9a0065..111505f 100644 --- a/primitives/generic_type.js +++ b/primitives/generic_type.js @@ -1,4 +1,4 @@ -import { constructorLeft, constructorRight } from "../structures/sum.js"; +import { newLeft, newRight } from "../structures/sum.js"; import { setType, sumType, typedFnType } from "../structures/types.js"; import { Any, GenericType, SymbolT, Type, Unit } from "./types.js"; import { unit } from "./unit.js"; @@ -7,8 +7,8 @@ export const getType = genericType => genericType.type; export const getTypeVars = genericType => genericType.typeVars; export const toNonGeneric = genericType => (genericType.typeVars.size === 0) - ? constructorRight(genericType.type) - : constructorLeft(unit); + ? newRight(genericType.type) + : newLeft(unit); export const ModuleGenericType = {l:[ {i: GenericType, t: Any}, diff --git a/stdlib.js b/stdlib.js index 9f6c1bf..0c5e726 100644 --- a/stdlib.js +++ b/stdlib.js @@ -12,14 +12,14 @@ import { ModuleList } from "./structures/list.js"; import { ModuleProduct } from "./structures/product.js"; import { ModuleSum } from "./structures/sum.js"; import { ModuleType } from "./primitives/type.js"; -import { ModuleTyped } from "./typed.js"; +import { ModuleDynamic } from "./primitives/dynamic.js"; import { ModuleSet } from "./structures/set.js"; import { ModuleGenericType } from "./primitives/generic_type.js"; export const ModuleStd = {l:[ ...ModuleType.l, ...ModuleGenericType.l, - ...ModuleTyped.l, + ...ModuleDynamic.l, ...ModuleTypeConstructor.l, ...ModuleSymbols.l, diff --git a/structures/enum.js b/structures/enum.js index d8c7786..34d74c6 100644 --- a/structures/enum.js +++ b/structures/enum.js @@ -1,7 +1,7 @@ import { Bottom } from "../primitives/types.js"; import { capitalizeFirstLetter } from "../util/util.js"; -import { constructorProduct, getLeft, getRight } from "./product.js"; -import { constructorLeft, constructorRight, match } from "./sum.js"; +import { newProduct as newProduct, getLeft, getRight } from "./product.js"; +import { newLeft, newRight, match } from "./sum.js"; import { sumType } from "./types.js"; // 'variants' is an array of (name: string, type: Type) pairs. @@ -34,7 +34,7 @@ export const makeMatchFn = variants => { const [_, ...remainingVariants] = variants; return sum => handler => { return ( - match(sum)(constructorProduct + match(sum)(newProduct (leftValue => eatParameters(remainingVariants.length, handler(leftValue))) (rightValue => makeMatchFn(remainingVariants)(rightValue)) )); @@ -48,10 +48,10 @@ export const makeConstructors = variants => { const [variant, ...remainingVariants] = variants; const name = getLeft(variant); const ctorName = `new${capitalizeFirstLetter(name)}`; - const constructor = { [ctorName]: val => constructorLeft(val) }[ctorName]; + const constructor = { [ctorName]: val => newLeft(val) }[ctorName]; return [ constructor, ...makeConstructors(remainingVariants).map(ctor => - ({[ctor.name]: val => constructorRight(ctor(val))}[ctor.name])), + ({[ctor.name]: val => newRight(ctor(val))}[ctor.name])), ]; } diff --git a/structures/list.js b/structures/list.js index d06eca5..2d409db 100644 --- a/structures/list.js +++ b/structures/list.js @@ -1,9 +1,9 @@ -import { fnType, typedFnType } from "./types.js"; +import { typedFnType } from "./types.js"; import { Char, GenericType, Type } from "../primitives/types.js"; import { Int } from "../primitives/types.js"; import { makeGeneric } from "../generics/generics.js"; import { lsType } from "./types.js"; -import { Typed } from "../typed.js" +import { Dynamic } from "../primitives/dynamic.js" // 'normal' implementation export const emptyList = {l:[]}; @@ -22,7 +22,7 @@ export const fold = ls => callback => initial => { } export const String = lsType(Char); // alias -export const Module = lsType(Typed); +export const Module = lsType(Dynamic); export const ModuleList = {l:[ // Type -> Type diff --git a/structures/product.js b/structures/product.js index af65c09..b66cb9e 100644 --- a/structures/product.js +++ b/structures/product.js @@ -9,7 +9,7 @@ import { typedFnType } from "./types.js"; import { prodType } from "./types.js"; // In JS, all products are encoded in the same way: -export const constructorProduct = l => r => ({l, r}); +export const newProduct = l => r => ({l, r}); export const getLeft = product => product.l; export const getRight = product => product.r; @@ -26,7 +26,7 @@ export const ModuleProduct = {l: [ ), // a -> b -> (a, b) - ...typedFnType(constructorProduct, fnType => + ...typedFnType(newProduct, fnType => makeGeneric((a, b) => fnType (a) diff --git a/structures/struct.js b/structures/struct.js index 649d54c..fa43919 100644 --- a/structures/struct.js +++ b/structures/struct.js @@ -1,7 +1,7 @@ import { Unit } from "../primitives/types.js"; import { unit } from "../primitives/unit.js"; import { capitalizeFirstLetter } from "../util/util.js"; -import { constructorProduct, getLeft, getRight } from "./product.js"; +import { newProduct, getLeft, getRight } from "./product.js"; import { fnType, prodType } from "./types.js"; // 'fields' is an array of (name: string, type: Type) pairs. @@ -26,7 +26,7 @@ export const makeConstructor = fields => { return nextParam => { const wrappedName = 'wrapped_' + ret.name; const newRet = { - [wrappedName]: inner => constructorProduct(nextParam)(ret(inner)), + [wrappedName]: inner => newProduct(nextParam)(ret(inner)), }[wrappedName]; return internal(nParams-1, newRet); } diff --git a/structures/sum.js b/structures/sum.js index 274588f..197f38d 100644 --- a/structures/sum.js +++ b/structures/sum.js @@ -8,8 +8,8 @@ import { typedFnType } from "./types.js"; import { makeGeneric } from "../generics/generics.js"; import { sumType } from "./types.js"; -export const constructorLeft = left => ({t: "L", v: left }); // 't': tag, 'v': value -export const constructorRight = right => ({t: "R", v: right}); +export const newLeft = left => ({t: "L", v: left }); // 't': tag, 'v': value +export const newRight = right => ({t: "R", v: right}); // signature: // sum-type -> (leftType -> resultType, rightType -> resultType) -> resultType @@ -31,7 +31,7 @@ export const ModuleSum = {l:[ ), // a -> a | b - ...typedFnType(constructorLeft, fnType => + ...typedFnType(newLeft, fnType => makeGeneric((a, b) => fnType (a) @@ -39,7 +39,7 @@ export const ModuleSum = {l:[ ), GenericType), // b -> a | b - ...typedFnType(constructorRight, fnType => + ...typedFnType(newRight, fnType => makeGeneric((a, b) => fnType (b) diff --git a/typed.js b/typed.js deleted file mode 100644 index b3a1d71..0000000 --- a/typed.js +++ /dev/null @@ -1,18 +0,0 @@ -import { typedFnType } from "./structures/types.js"; -import { Any, Type } from "./primitives/types.js"; -import { makeTypeConstructor } from "./type_constructor.js"; - -// A type-link, connecting a value to its Type. -const symbolTyped = Symbol('Typed'); -export const Typed = makeTypeConstructor(symbolTyped)(0); - -const getInst = lnk => lnk.i; -const getType = lnk => lnk.t; - -export const ModuleTyped = {l:[ - {i: Typed, t: Type}, - {i: Any , t: Type}, - - ...typedFnType(getInst, fnType => fnType(Typed)(Any)), - ...typedFnType(getType, fnType => fnType(Typed)(Any)), -]}; diff --git a/versioning/types.js b/versioning/types.js new file mode 100644 index 0000000..8068653 --- /dev/null +++ b/versioning/types.js @@ -0,0 +1,26 @@ +import { Dynamic } from "../primitives/dynamic.js"; +import { Int } from "../primitives/types.js"; +import { enumType } from "../structures/enum.js"; +import { newProduct } from "../structures/product.js"; +import { structType } from "../structures/struct.js"; +import { prettyT, prodType } from "../structures/types.js"; + +const Slot = structType([ + newProduct("value")(() => Value), + newProduct("depth")(() => Int), + newProduct("overwrites")(() => Slot), +]); + +// A Value is either: +// - a literal, without any dependencies. +// - read from a slot. the Value then has a read-dependency on that slot. +// - a transformation of another Value, by a function. the function is also a Value. +const variants = [ + newProduct("literal", () => Dynamic), + newProduct("read", () => Slot), + newProduct("transformation", () => prodType(Value, Dynamic)), +]; +const Value = enumType(variants); + +// console.log(prettyT(Slot)); +// console.log(prettyT(Value)); \ No newline at end of file