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:
Joeri Exelmans 2025-04-04 10:04:40 +02:00
parent 8ac0c6d3dd
commit 342d4b34ef
2 changed files with 32 additions and 7 deletions

View file

@ -140,12 +140,14 @@ const unifyInternal = (typeVars, fType, aType) => {
};
export const unify = (fGenericType, aGenericType) => {
let allTypeVars;
[allTypeVars, fGenericType, aGenericType] = safeUnionTypeVars(fGenericType, aGenericType);
const {genericType} = unifyInternal(
fGenericType.typeVars.union(aGenericType.typeVars),
allTypeVars,
fGenericType.type,
aGenericType.type,
)
return genericType;
return recomputeTypeVars(genericType);
}
export const substitute = (type, substitutions) => {
@ -163,18 +165,41 @@ export const substitute = (type, substitutions) => {
};
export const assign = (genFnType, paramType) => {
let allTypeVars;
[allTypeVars, genFnType, paramType] = safeUnionTypeVars(genFnType, paramType);
const [inType, outType] = genFnType.type.params;
const allTypeVars = genFnType.typeVars.union(paramType.typeVars)
const {substitutions} = unifyInternal(allTypeVars, inType, paramType.type);
const substitutedOutType = substitute(outType, substitutions);
return onlyOccurring(substitutedOutType, allTypeVars);
return recomputeTypeVars(onlyOccurring(substitutedOutType, allTypeVars));
};
export const assignFn = (genFnType, paramType) => {
let allTypeVars;
[allTypeVars, genFnType, paramType] = safeUnionTypeVars(genFnType, paramType);
const [inType] = genFnType.type.params;
const allTypeVars = genFnType.typeVars.union(paramType.typeVars)
const {substitutions} = unifyInternal(allTypeVars, inType, paramType.type);
// console.log({genFnType: prettyT(genFnType), paramType: prettyT(paramType), 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];
}