diff --git a/lib/generics/generics.js b/lib/generics/generics.js index f5688b1..343c765 100644 --- a/lib/generics/generics.js +++ b/lib/generics/generics.js @@ -88,7 +88,7 @@ export class NotAFunctionError extends Error {} // typeVars: all the type variables in both fType and aType // fType, aType: generic types to unify // fStack, aStack: internal use. -const __unify = (fType, aType, fStack=[], aStack=[]) => { +export const __unify = (fType, aType, fStack=[], aStack=[]) => { // console.log("__unify", {typeVars, fType: prettyT(fType), aType: prettyT(aType), fStack, aStack}); if (isTypeVar(fType)) { // simplest case: formalType is a type paramater @@ -196,18 +196,22 @@ export const assignFnSubstitutions = (funType, paramType) => { if (getSymbol(funType) !== symbolFunction) { throw new NotAFunctionError(`${prettyT(funType)} is not a function type!`); } - [funType, paramType] = recomputeTypeVars([funType, paramType]); - // console.log(prettyT(funType), prettyT(paramType)); - const [inType, outType] = funType.params.map(p => p(funType)); - const {substitutions} = __unify(inType, paramType); + const [[refunType, funS], [reparamType, paramS]] = recomputeTypeVarsSubstitutions([funType, paramType]); + const [inType, outType] = refunType.params.map(p => p(refunType)); + const {substitutions} = __unify(inType, reparamType); // console.log(substitutions, prettyT(outType)); const substitutedFnType = substitute(outType, substitutions); const computedOutType = recomputeTypeVars([substitutedFnType])[0]; return [computedOutType, substitutions]; -} +}; // Ensures that no type variables overlap export const recomputeTypeVars = types => { + return recomputeTypeVarsSubstitutions(types) + .map(([newType, _subst]) => newType); +}; + +export const recomputeTypeVarsSubstitutions = types => { let nextIdx = 0; return types.map(type => { const substitutions = new Map(); @@ -215,6 +219,6 @@ export const recomputeTypeVars = types => { for (const typeVar of typeVars) { substitutions.set(typeVar, TYPE_VARS[nextIdx++]); } - return substitute(type, substitutions); + return [substitute(type, substitutions), substitutions]; }); -} +};