If a variable x is absent from pair'.ctx and pair.ctx extends pair'.ctx with a
binding for x, then type-checking any term m (where Term.var x ≠ m) in pair.ctx
yields the same result as in pair'.ctx. In other words, adding an unused variable to the
context does not affect checking.
Applying a type substitution s to every type in a context maps a successful check result
covariantly: if check ctx t = some ty then check (applySubst s ctx) t = some (s ty).
Composing two substitution applications is the same as applying their functional composition.
That is, applySubst f (applySubst g ctx) = applySubst (f ∘ g) ctx.
Applying a substitution to a context and then advancing to the next fresh variable yields the
same check result as applying the substitution to the already-advanced context. In other words,
applySubst and next commute as far as check is concerned.
This is a corollary of CheckInvUnderLabel.
applySubst preserves the env field of a context (up to value substitution), so two
contexts with equal environments produce equal environments after the same substitution.
If a Subst s1 distributes over arrows
(i.e. s1.apply ab = (s1.apply a).arrow (s1.apply b)),
then composing with a CtxSubst s2 preserves this arrow structure.
If pp' ctx m = some ⟨ctx', ty⟩, then there exists a substitution f such that
(applySubst f ctx).env ⊆ ctx'.env. In other words, the inference output context
contains the input context (up to substitution).
distributes f: predicate asserting that f distributes over arrow types,
i.e. f (a → b) = f(a) → f(b). Required by CheckSubst.
Instances For
lookup_inv f ctx ctx':
predicate asserting that f is a lookup invariant from ctx to ctx',
i.e. for every variable x with type ty in ctx, ctx' assigns f ty to x.
Equations
Instances For
check_inv f ctx ctx': predicate asserting that f is a check invariant from ctx to ctx',
i.e. for every term t with type ty under ctx, ctx' assigns f ty to t.
Equations
Instances For
equiv_lookup_on f g ctx: f and g agree on types of variables actually occurring in ctx,
i.e. for all x with ctx.lookup x = some ty, g ty = f ty.
Equations
Instances For
equiv_check_on f g ctx: f and g agree on types of terms that type-check under ctx,
i.e. for all t with check ctx t = some ty, g ty = f ty.
Equations
Instances For
InferenceLookupInv: if pp' ctx m = some ⟨ctx', _⟩, then there exists a canonical
substitution f (distributing over arrows) that is a lookup invariant from ctx to ctx',
and it is unique in the sense that any other lookup invariant g agrees with f on
types occurring in ctx.
InferenceCheckInv: if pp' ctx m = some ⟨ctx', _⟩, then there exists a canonical
substitution f (distributing over arrows) that is a check invariant from ctx to ctx',
and it is unique among check invariants in that any other g agrees with f on types
of terms typeable under ctx.
occursInTerm x t:
proposition that variable x occurs (free or bound as a name) in term t.
Equations
- occursInTerm x (Term.var y) = (x = y)
- occursInTerm x (Term.abs y m) = (x = y ∨ occursInTerm x m)
- occursInTerm x (m.app n) = (occursInTerm x m ∨ occursInTerm x n)
Instances For
CheckEqIfOccursInv: if two contexts agree on the types of all variables occurring in t,
then check ctx1 t = check ctx2 t.
UnifyCtxMapCommon: if unifyCtx ctx1 ctx2 = some s, then for any variable x whose
type is ty1 in ctx1 and ty2 in ctx2, the substitution s unifies them:
s.apply ty1 = s.apply ty2. This is the soundness property of unifyCtx.
Soundness of the principal-type algorithm helper pp': if pp' ctx t = some pair, then
t is well-typed in pair.ctx with type pair.ty, i.e. check pair.ctx t = some pair.ty.