import { fnType, prodType, sumType } from "../type_registry.js"; import { Function, Type } from "../metacircular.js"; import { Module } from "./module.js"; const constructorLeft = left => ({variant: "L", value: left }); const constructorRight = right => ({variant: "R", value: right}); // (, product(double, double)): product(int, type) // signature: // sum-type -> (leftType -> resultType, rightType -> resultType) -> resultType const match = sum => handlers => sum.variant === "L" ? handlers.left(sum.value) : handlers.right(sum.value); // Given two types A and B, create the type (A + B). export const makeSumType = (leftType, rightType) => { const sType = sumType(leftType, rightType); const constructorLeftType = fnType({in: leftType , out: sType}); const constructorRightType = fnType({in: rightType, out: sType}); // For each possible return type, the match function has a different signature. // We thus define a function that creates a properly typed match function. const makeMatchFn = returnType => { const handlersType = prodType( fnType({in: leftType , out: returnType}), // handler function for left variant fnType({in: rightType, out: returnType}), // handler function for right variant ); const matchFnType = fnType({in: sType, out: fnType({in: handlersType, out: returnType})}); return {l:[ {i: match , t: matchFnType}, {i: matchFnType, t: Function}, ]}; }; return {l:[ {i: sType , t: Type}, {i: constructorLeft , t: constructorLeftType}, {i: constructorRight , t: constructorRightType}, {i: constructorLeftType , t: Function}, {i: constructorRightType, t: Function}, {i: makeMatchFn, t: fnType({in: Type, out: Module})}, ]}; };