import { prodType } from "./product.js"; import { Type } from "../metacircular.js"; import { DefaultMap } from "../util.js"; import { typedFnType } from "./function.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); const constructorLeft = left => ({variant: "L", value: left }); const constructorRight = right => ({variant: "R", value: right}); // signature: // sum-type -> (leftType -> resultType, rightType -> resultType) -> resultType const match = sum => handlers => sum.variant === "L" ? handlers.left(sum.value) : handlers.right(sum.value); export const ModuleSum = {l:[ // binary type constructor // Type -> Type -> Type ...typedFnType(sumType, fnType => fnType (Type) (fnType (Type) (Type) ), ), // a -> 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)) )), // 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) ) )), ]};