Composition is the act of taking a stack and a function, and producing the type signature of the resulting stack. It can also be equivalenty seen as the composition of two functions' execution.
- Generate constraints from the stated type sigs of your functions.
- Match the RHS of the LHF, and the LHS of the RHF, from right to left. If the two symbols are:
- Base types: Fail if one is not a parent type of the other. Otherwise, move on.
- Both function types: Recursively generate constraints, starting with
{a} = {b}and expanding the functions using the function expansion rule:{a--b}->{c a--c b}. until one constraint set successfully unifies. If nothing works, fail. - One is a variardic type: Move past the variardic types until both symbols being compared are finite ones.
- Else: generate a constraint
a = band move on.
- When one side runs out of symbols, you can divide the other side into its matched and unmatched symbols. Save these for step (5).
- Compute the closure of the constraint set. Here are some basic rules:
{A -- B} = {C -- D}toA = CandB = DA?B = C?DtoA = CandB = DA = BandB = CtoA = CA = BtoB = A(maybe? Is this an equality or subtyping relation?)A = B AtoB =A B = C DtoA = CandB = DIFF they're all finite typesA B C = DandB = EtoA E C = D(an extension of the transitive property above)
- Find the combined signature of the first unification that succeeds.
If you unify
a -- b xandc x -- d, wherexis the matched portion andb/care unmatched ones, you getc a -- b d. Note that eitherborcmust be empty because of how matching works. - For each type variable, find all the consrtaints the mention it and find the most specific type among them. Replace.
UNIFY (-- {(?) -- Int?Int}.) AND (C A {C A -- C A?B} -- C B; *A; *B; *C.):
CONSTRAINTS:
A = All*
B = All*
C = All*
{(?) -- (?)?Int} = {C A -- C A?B}
(?) = C A
(?)?Int = A?B
(?) = A
Int = B
(?) = C (?)
C =
WE KNOW:
A = (?); B = Int; C = ;
FINALLY:
C A -- C B
(?) -- Int
Function expansion of {a--b} to {c a--c b} is nice and all, and accurately reflects how functions work, but is it sound inside composition? Does it generate cases where the type signature informs the behavior of the function? That would be bad.