There is one final aspect of the inference algorithm that requires study before we look at the individual pieces: the generalization operation.92 That said, in terms of understanding the Bake algorithm, having a strong grasp on generalization is not terribly important; this is merely a technical step needed to make the mathematics hold together.
Suppose we are synthesizing the type of a λ-expression λx → τ. We choose a unification variableα for the type ofx. We then must putx:Relαinto the context when
synthesizing the type forτ. Synthesizing this type will produce a unification telescope
Ω. Now we have a problem: what unification telescope will we return from synthesizing the type of the entire λ-expression? It looks something like α:IrrelType,x:Relα,Ωbut,
critically, that is not a unification telescope, as that context contains a binding for an ordinary Picovariable, x.
91Although not visible in the simplified presentation of
Sub_DeepSkolin Figure 6.4 on page 155,
it is critical thatκ2 is skolemizedbefore κ1 is instantiated, lest we end up with the same scoping
problem. This can be seen in the full rule (Section D.9) with the fact that we includeΩ1 in the final
generalization step. In contrast to other potential pitfalls mentioned earlier, leavingΩ1 out of this
line does not imperil the soundness of elaboration; it is only a matter of expressiveness of the source Haskell.
92What I call generalization here is precisely what Gundry [37, Section 7.5] calls “parameterisation”
Ω,→∆ Ω0;ξ Generalize Ωover ∆. ∅,→∆ ∅;∅ IGen_Nil ξ0 = α7→dom(∆) Ω[ξ0],→∆ Ω0;ξ α:ρ∀∆0.κ,Ω,→∆ α:ρ∀∆,∆0.κ,Ω0;ξ0, ξ IGen_TyVar ξ0 = ι7→dom(∆) Ω[ξ0],→∆ Ω0;ξ ι: ∀∆0.φ,Ω,→∆ ι: ∀∆,∆0.φ,Ω0;ξ 0, ξ IGen_CoVar
Figure 6.5: Bake’s generalization operation
It might be tempting at this point simply to return a mixed telescope of unification variables and Picovariables, and just to carry on. The problem here is that we will lose track of the local scope ofx. Perhaps something later, outside of the λ-expression, will end up unifying with x—which would be a disaster. No, we must get rid of it.
The solution is to generalizeΩ overx. This operation is writtenΩ,→x:RelType
Ω0;ξ. (The mnemonic behind the choice of ,→is that we are essentially moving the
x:RelType binding to the right, past Ω.) The output unification telescope Ω0 binds
the same unification variables as Ω, but each one will be generalized with respect to x. The definition of this judgment appears in Figure 6.5. The rules are a bit complicated by the fact that we may generalize a unification variable binding multiple times; both recursive rules thus assume a telescope ∆0 that has already been generalized.
The new construct ξ is a generalizer. It is a substitution-like construct that maps unification variables to vectors, which you may recall are lists of arguments ψ. In this case, we simply use the domain of ∆ as the vector, where my use of dom(∆)
as a list of arguments means to insert the irrelevance braces around irrelevantly bound variables. Generalizers are necessary because generalizing changes the type of unification variables; we must then change the occurrences of them as well.
Generalizers operate like this:
Definition (Generalizing [Definition E.31]). A generalizer is applied postfix as a function. It operates homomorphically on all recursive forms and as the identity operation on leaves other than unification variables. Generalizing unification variables is defined by these equations:
α7→ψ1 ∈ξ ⇒ αψ 2[ξ] = αψ1,ψ2 otherwise αψ[ξ] = αψ[ξ] ι7→ψ1 ∈ξ ⇒ ιψ 2[ξ] = ιψ1,ψ2 otherwise ιψ[ξ] = ιψ[ξ]
Just like the generalization judgment (Figure 6.5), the generalization operation [ξ]
Σ; Ψ `ty t τ :κaΩ synthesize a type (no invis. binders) Σ; Ψ `
∗
ty t τ :κaΩ synthesize a type
Σ; Ψ `ty t :κ τ aΩ check a type (no invis. binders)
Σ; Ψ `
∗
ty t :κ τ aΩ check a type
Σ; Ψ `pt s τ aΩ check a polytype (always with kind Type)
Σ; Ψ;ρ`
∗
arg t :κ ψ;τ aΩ check an argument at relevance ρ
Σ; Ψ;κ0;τ0 `altalt :κ alt aΩ check a case alt. against an unknown type
Σ; Ψ;κ0;τ0 `altc alt :κ alt aΩ check a case alt. against a known type
Σ; Ψ`q qvar a :κ;ν aΩ synth. type of a bound var.
Σ; Ψ `aqaqvar a :κaΩ synth. type of a bound var. (w/o vis. marker)
Σ; Ψ `aqaqvar :κ a :κ0;x.τ aΩ check type of a bound var. (w/o vis. marker)
`
piquant Π;ρ interpret a quantifier
`
fun κ;ρ1 γ; Π;a;ρ2;κ1;κ2 aΩ extract components of a function type
Σ; Ψ`scrutalt;κ γ; ∆;H;τ aΩ extract components of a scrutinee type
` ν inst κ ψ;κ 0 a Ω instantiate a type
Σ; Γ`decl decl x :κ:=τ check a declaration
Σ; Γ`prog prog Γ0;θ check a program
Figure 6.6: Bake judgments