export __unify
This commit is contained in:
parent
0096bb5559
commit
8266e59b94
1 changed files with 12 additions and 8 deletions
|
|
@ -88,7 +88,7 @@ export class NotAFunctionError extends Error {}
|
||||||
// typeVars: all the type variables in both fType and aType
|
// typeVars: all the type variables in both fType and aType
|
||||||
// fType, aType: generic types to unify
|
// fType, aType: generic types to unify
|
||||||
// fStack, aStack: internal use.
|
// 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});
|
// console.log("__unify", {typeVars, fType: prettyT(fType), aType: prettyT(aType), fStack, aStack});
|
||||||
if (isTypeVar(fType)) {
|
if (isTypeVar(fType)) {
|
||||||
// simplest case: formalType is a type paramater
|
// simplest case: formalType is a type paramater
|
||||||
|
|
@ -196,18 +196,22 @@ export const assignFnSubstitutions = (funType, paramType) => {
|
||||||
if (getSymbol(funType) !== symbolFunction) {
|
if (getSymbol(funType) !== symbolFunction) {
|
||||||
throw new NotAFunctionError(`${prettyT(funType)} is not a function type!`);
|
throw new NotAFunctionError(`${prettyT(funType)} is not a function type!`);
|
||||||
}
|
}
|
||||||
[funType, paramType] = recomputeTypeVars([funType, paramType]);
|
const [[refunType, funS], [reparamType, paramS]] = recomputeTypeVarsSubstitutions([funType, paramType]);
|
||||||
// console.log(prettyT(funType), prettyT(paramType));
|
const [inType, outType] = refunType.params.map(p => p(refunType));
|
||||||
const [inType, outType] = funType.params.map(p => p(funType));
|
const {substitutions} = __unify(inType, reparamType);
|
||||||
const {substitutions} = __unify(inType, paramType);
|
|
||||||
// console.log(substitutions, prettyT(outType));
|
// console.log(substitutions, prettyT(outType));
|
||||||
const substitutedFnType = substitute(outType, substitutions);
|
const substitutedFnType = substitute(outType, substitutions);
|
||||||
const computedOutType = recomputeTypeVars([substitutedFnType])[0];
|
const computedOutType = recomputeTypeVars([substitutedFnType])[0];
|
||||||
return [computedOutType, substitutions];
|
return [computedOutType, substitutions];
|
||||||
}
|
};
|
||||||
|
|
||||||
// Ensures that no type variables overlap
|
// Ensures that no type variables overlap
|
||||||
export const recomputeTypeVars = types => {
|
export const recomputeTypeVars = types => {
|
||||||
|
return recomputeTypeVarsSubstitutions(types)
|
||||||
|
.map(([newType, _subst]) => newType);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const recomputeTypeVarsSubstitutions = types => {
|
||||||
let nextIdx = 0;
|
let nextIdx = 0;
|
||||||
return types.map(type => {
|
return types.map(type => {
|
||||||
const substitutions = new Map();
|
const substitutions = new Map();
|
||||||
|
|
@ -215,6 +219,6 @@ export const recomputeTypeVars = types => {
|
||||||
for (const typeVar of typeVars) {
|
for (const typeVar of typeVars) {
|
||||||
substitutions.set(typeVar, TYPE_VARS[nextIdx++]);
|
substitutions.set(typeVar, TYPE_VARS[nextIdx++]);
|
||||||
}
|
}
|
||||||
return substitute(type, substitutions);
|
return [substitute(type, substitutions), substitutions];
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue