fix bug in polymorphic types (when creating a tuple of two empty lists, there was only one type variable (the type of the list), whereas each list could have a different type, so there should be two type variables) + make type variables look nicer
This commit is contained in:
parent
8ac0c6d3dd
commit
342d4b34ef
2 changed files with 32 additions and 7 deletions
|
|
@ -140,12 +140,14 @@ const unifyInternal = (typeVars, fType, aType) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const unify = (fGenericType, aGenericType) => {
|
export const unify = (fGenericType, aGenericType) => {
|
||||||
|
let allTypeVars;
|
||||||
|
[allTypeVars, fGenericType, aGenericType] = safeUnionTypeVars(fGenericType, aGenericType);
|
||||||
const {genericType} = unifyInternal(
|
const {genericType} = unifyInternal(
|
||||||
fGenericType.typeVars.union(aGenericType.typeVars),
|
allTypeVars,
|
||||||
fGenericType.type,
|
fGenericType.type,
|
||||||
aGenericType.type,
|
aGenericType.type,
|
||||||
)
|
)
|
||||||
return genericType;
|
return recomputeTypeVars(genericType);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const substitute = (type, substitutions) => {
|
export const substitute = (type, substitutions) => {
|
||||||
|
|
@ -163,18 +165,41 @@ export const substitute = (type, substitutions) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const assign = (genFnType, paramType) => {
|
export const assign = (genFnType, paramType) => {
|
||||||
|
let allTypeVars;
|
||||||
|
[allTypeVars, genFnType, paramType] = safeUnionTypeVars(genFnType, paramType);
|
||||||
const [inType, outType] = genFnType.type.params;
|
const [inType, outType] = genFnType.type.params;
|
||||||
const allTypeVars = genFnType.typeVars.union(paramType.typeVars)
|
|
||||||
const {substitutions} = unifyInternal(allTypeVars, inType, paramType.type);
|
const {substitutions} = unifyInternal(allTypeVars, inType, paramType.type);
|
||||||
const substitutedOutType = substitute(outType, substitutions);
|
const substitutedOutType = substitute(outType, substitutions);
|
||||||
return onlyOccurring(substitutedOutType, allTypeVars);
|
return recomputeTypeVars(onlyOccurring(substitutedOutType, allTypeVars));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const assignFn = (genFnType, paramType) => {
|
export const assignFn = (genFnType, paramType) => {
|
||||||
|
let allTypeVars;
|
||||||
|
[allTypeVars, genFnType, paramType] = safeUnionTypeVars(genFnType, paramType);
|
||||||
const [inType] = genFnType.type.params;
|
const [inType] = genFnType.type.params;
|
||||||
const allTypeVars = genFnType.typeVars.union(paramType.typeVars)
|
|
||||||
const {substitutions} = unifyInternal(allTypeVars, inType, paramType.type);
|
const {substitutions} = unifyInternal(allTypeVars, inType, paramType.type);
|
||||||
// console.log({genFnType: prettyT(genFnType), paramType: prettyT(paramType), substitutions})
|
// console.log({genFnType: prettyT(genFnType), paramType: prettyT(paramType), substitutions})
|
||||||
const substitutedFnType = substitute(genFnType.type, substitutions);
|
const substitutedFnType = substitute(genFnType.type, substitutions);
|
||||||
return onlyOccurring(substitutedFnType, allTypeVars);
|
return recomputeTypeVars(onlyOccurring(substitutedFnType, allTypeVars));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const recomputeTypeVars = (genType) => {
|
||||||
|
const newTypeVars = ['a', 'b', 'c', 'd', 'e', 'f', 'g'].map(Symbol);
|
||||||
|
let nextIdx = 0;
|
||||||
|
const subst = new Map();
|
||||||
|
for (const typeVarA of genType.typeVars) {
|
||||||
|
subst.set(typeVarA, newTypeVars[nextIdx++]);
|
||||||
|
}
|
||||||
|
const substType = {
|
||||||
|
typeVars: new Set(subst.values()),
|
||||||
|
type: substitute(genType.type, subst),
|
||||||
|
};
|
||||||
|
return substType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const safeUnionTypeVars = (genTypeA, genTypeB) => {
|
||||||
|
const substTypeA = recomputeTypeVars(genTypeA);
|
||||||
|
const substTypeB = recomputeTypeVars(genTypeB);
|
||||||
|
const allTypeVars = substTypeA.typeVars.union(substTypeB.typeVars);
|
||||||
|
return [allTypeVars, substTypeA, substTypeB];
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +62,7 @@ export function prettyT(type) {
|
||||||
}
|
}
|
||||||
if (type.typeVars) {
|
if (type.typeVars) {
|
||||||
if (type.typeVars.size > 0) {
|
if (type.typeVars.size > 0) {
|
||||||
return `∀(${[...type.typeVars].map(prettyT).join(", ")}): ${prettyT(type.type)}`;
|
return `∀${[...type.typeVars].map(prettyT).sort((a,b)=>a.localeCompare(b)).join(",")}: ${prettyT(type.type)}`;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return prettyT(type.type);
|
return prettyT(type.type);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue