cleanup unification a bit
This commit is contained in:
parent
68bd7cdb9f
commit
2333abe70f
1 changed files with 24 additions and 10 deletions
|
|
@ -29,6 +29,7 @@ export class SubstitutionCycle extends Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pure
|
||||||
export const subsitutionsEqual = (m1,m2) => {
|
export const subsitutionsEqual = (m1,m2) => {
|
||||||
if (m1.size !== m2.size ) return false;
|
if (m1.size !== m2.size ) return false;
|
||||||
for (const [key1,type1] of m1) {
|
for (const [key1,type1] of m1) {
|
||||||
|
|
@ -37,6 +38,7 @@ export const subsitutionsEqual = (m1,m2) => {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// pure
|
||||||
// Partial ordering between types
|
// Partial ordering between types
|
||||||
// - deep-equal types are equal (e.g., Int == Int)
|
// - deep-equal types are equal (e.g., Int == Int)
|
||||||
// - non-typevars are smaller than typevars (e.g., Int < a)
|
// - non-typevars are smaller than typevars (e.g., Int < a)
|
||||||
|
|
@ -68,17 +70,20 @@ const partialCompareTypes = (typeA, typeB) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pure
|
||||||
const checkCycle = (typevar, type) => {
|
const checkCycle = (typevar, type) => {
|
||||||
if (occurring(type).has(typevar)) {
|
if (occurring(type).has(typevar)) {
|
||||||
throw new SubstitutionCycle(typevar, type);
|
throw new SubstitutionCycle(typevar, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// impure, modifies 'substitutions'
|
||||||
const addReduce = (substitutions, typevar, type) => {
|
const addReduce = (substitutions, typevar, type) => {
|
||||||
// console.log('add ', prettyS(typevar, type));
|
// console.log('add ', prettyS(typevar, type));
|
||||||
substitutions.set(typevar, type);
|
substitutions.set(typevar, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// impure, modifies 'substitutions'
|
||||||
const attemptReduce = (substitutions, typevar, type) => {
|
const attemptReduce = (substitutions, typevar, type) => {
|
||||||
// assuming 'substitutions' is already reduced as much as possible,
|
// assuming 'substitutions' is already reduced as much as possible,
|
||||||
// substitute all typevars in our type with the existing substitutions
|
// substitute all typevars in our type with the existing substitutions
|
||||||
|
|
@ -108,8 +113,24 @@ const attemptReduce = (substitutions, typevar, type) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pure
|
||||||
|
export const mergeSubstitutionsN = (substs) => {
|
||||||
|
return substs.reduce((acc, cur) => {
|
||||||
|
return mergeSubstitutions2(acc, cur);
|
||||||
|
}, new Map());
|
||||||
|
}
|
||||||
|
|
||||||
|
// pure
|
||||||
|
const mergeSubstitutions2 = (substA, substB) => {
|
||||||
|
const result = new Map(substA);
|
||||||
|
for (const [typevarB, typeB] of substB) {
|
||||||
|
attemptReduce(result, typevarB, typeB);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pure
|
||||||
export const unify = (typeA, typeB) => {
|
export const unify = (typeA, typeB) => {
|
||||||
const substitutions = new Map();
|
|
||||||
try {
|
try {
|
||||||
if (isTypeVar(typeA)) {
|
if (isTypeVar(typeA)) {
|
||||||
if (isTypeVar(typeB)) {
|
if (isTypeVar(typeB)) {
|
||||||
|
|
@ -139,20 +160,14 @@ export const unify = (typeA, typeB) => {
|
||||||
throw new IncompabibleTypesError(typeA, typeB);
|
throw new IncompabibleTypesError(typeA, typeB);
|
||||||
}
|
}
|
||||||
|
|
||||||
const unifiedParams = zip(typeA.params, typeB.params)
|
const subs = zip(typeA.params, typeB.params)
|
||||||
.map(([getParamA, getParamB]) => {
|
.map(([getParamA, getParamB]) => {
|
||||||
const paramA = getParamA(typeA);
|
const paramA = getParamA(typeA);
|
||||||
const paramB = getParamB(typeB);
|
const paramB = getParamB(typeB);
|
||||||
// console.log('request...');
|
// console.log('request...');
|
||||||
return unify(paramA, paramB);
|
return unify(paramA, paramB);
|
||||||
});
|
});
|
||||||
|
return mergeSubstitutionsN(subs);
|
||||||
// merge substitutions
|
|
||||||
unifiedParams.forEach(subst => {
|
|
||||||
for (const [typevar, type] of subst) {
|
|
||||||
attemptReduce(substitutions, typevar, type);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (e instanceof SubstitutionCycle) {
|
if (e instanceof SubstitutionCycle) {
|
||||||
|
|
@ -164,5 +179,4 @@ export const unify = (typeA, typeB) => {
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
return substitutions;
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue