Qualified Types, Type Classes, and Coherent Dictionary Elaboration
Prerequisites. Direct starred prerequisites: none. No later core chapter depends on this route.
A class names a collection of operations indexed by a type; its operations are its methods. An instance implements those operations at a particular type constructor. At run time the implementation is carried by a dictionary, an ordinary record of method values. A superclass edge requires every dictionary for the subclass to carry a dictionary for the superclass. These meanings govern the motivating example as well as the calculus below.
The term 𝗌𝖺𝗆𝖾:=𝜆𝑥.𝖾𝗊𝑥𝑥 is the smallest obstruction. Hindley–Milner can assign ∀𝐴.𝐴→𝖡𝗈𝗈𝗅 when eq is itself assigned the scheme ∀𝐴.𝐴→𝐴→𝖡𝗈𝗈𝗅. Parametricity then makes that assignment too strong: a parametric function at the latter scheme is constant. Given (𝑎1,𝑎2)∈𝐴2 and (𝑏1,𝑏2)∈𝐵2, use the relation 𝑅={(𝑎1,𝑏1),(𝑎2,𝑏2)}; parametricity relates the two Boolean results by Boolean equality. Since both pairs were arbitrary, all results agree. Real equality is not constant. Conversely, if a caller may silently choose either the usual integer equality dictionary or a dictionary that always returns false, same 0 has two answers. A useful account of overloading must therefore say both where an operation comes from and why its choice is stable.
One finite qualified-type calculus
Typing 𝗌𝖺𝗆𝖾 generates a class request 𝖤𝗊𝛼; entailment constructs the dictionary passed to 𝖾𝗊. These class requests are distinct from the row lacks predicates of chapter 4.
For example, a superclass edge from 𝖮𝗋𝖽 to 𝖤𝗊 requires every 𝖮𝗋𝖽 dictionary to contain an 𝖤𝗊 dictionary. Thus an 𝖮𝗋𝖽𝖨𝗇𝗍 instance determines both integer order and integer equality; the projections below make that containment explicit.
Call the calculus QTC0. Its monotypes, predicates, and schemes are 𝜏::=𝛼∣𝖨𝗇𝗍∣𝖡𝗈𝗈𝗅∣𝖲𝗍𝗋𝗂𝗇𝗀∣𝖫𝗂𝗌𝗍𝜏∣𝜏→𝜏,𝑝::=𝐾𝜏,𝑃,𝑄::={𝑝1,…,𝑝𝑛},𝜎::=∀¯𝛼.𝑃⇒𝜏. Class names are unary. Predicate sets are finite, not multisets. A class environment C=(S,I) contains
a finite acyclic superclass graph S; and
finitely many primitive instance clauses 𝑃⇒𝐾(𝐶¯𝜏), where 𝐶 is a type constructor, every premise is headed by a proper subterm of 𝐶¯𝜏, and no two instance heads for the same class unify.
Without superclass closure, substitution can change which dictionary should be selected. If 𝖮𝗋𝖽 has superclass 𝖤𝗊 and the only primitive clauses are 𝖮𝗋𝖽𝖨𝗇𝗍,𝖮𝗋𝖽𝛼⇒𝖮𝗋𝖽(𝖫𝗂𝗌𝗍𝛼), then substituting 𝛼:=𝖨𝗇𝗍 turns an 𝖤𝗊(𝖫𝗂𝗌𝗍𝛼) request into a projection from a constructible 𝖮𝗋𝖽 dictionary, although the unclosed table has no matching 𝖤𝗊 clause. The missing derived projection is the reason for closing the table before resolution.
Resolution uses the finite effective tableI↑. Fix a total order on class names and, at each class, on its outgoing superclass edges. Paths are ordered first by length and then lexicographically by those edge orders. For every primitive clause 𝑖:𝑃⇒𝐾′(𝐶¯𝜏) and every superclass 𝐾 reachable from 𝐾′, including 𝐾′ itself, choose the fixed shortest class/path-order path and add 𝑖𝐾:𝑃⇒𝐾(𝐶¯𝜏). Its evidence builder is the primitive constructor followed by the path projection, made explicit below. The empty path is the identity. After this closure, no two effective result heads for the same requested class may unify. Checking nonoverlap only in the primitive table is insufficient: a direct 𝖤𝗊𝖨𝗇𝗍 clause would overlap the derived projection of an 𝖮𝗋𝖽𝖨𝗇𝗍 clause. Rejecting that pair, rather than choosing between possibly different dictionaries, is what makes normalization substitution-stable without assuming class laws. Superclass closure is finite because the class graph and primitive table are finite.
There are no variable-headed instances, uncontrolled overlap, local instances, or class defaults. These restrictions are a termination and coherence policy: for one source program, every selected elaboration constructs the same evidence up to alpha-equivalence. This is not a claim about production Haskell. Our running environment C0 is 𝖮𝗋𝖽hassuperclass𝖤𝗊,𝖮𝗋𝖽𝖨𝗇𝗍,𝖤𝗊𝛼⇒𝖤𝗊(𝖫𝗂𝗌𝗍𝛼),𝖲𝗁𝗈𝗐𝖨𝗇𝗍. In particular, it has no 𝖲𝗁𝗈𝗐𝖡𝗈𝗈𝗅 instance. The two source methods have the schemes 𝖾𝗊:∀𝛼.𝖤𝗊𝛼⇒𝛼→𝛼→𝖡𝗈𝗈𝗅,𝗌𝗁𝗈𝗐:∀𝛼.𝖲𝗁𝗈𝗐𝛼⇒𝛼→𝖲𝗍𝗋𝗂𝗇𝗀.
Entailment constructs evidence
For each class, fix an ordinary target dictionary type. The examples use 𝖤𝗊𝐷(𝐴):=𝐴→𝐴→𝖡𝗈𝗈𝗅,𝖮𝗋𝖽𝐷(𝐴):=𝖤𝗊𝐷(𝐴)×(𝐴→𝐴→𝖡𝗈𝗈𝗅),𝖲𝗁𝗈𝗐𝐷(𝐴):=𝐴→𝖲𝗍𝗋𝗂𝗇𝗀. For the running table, fix target constants 𝗈𝗋𝖽𝖨𝗇𝗍:𝖮𝗋𝖽𝐷(𝖨𝗇𝗍),𝖾𝗊𝖫𝗂𝗌𝗍:∀𝐴.𝖤𝗊𝐷(𝐴)→𝖤𝗊𝐷(𝖫𝗂𝗌𝗍𝐴). If primitive instance 𝑖 has constructor 𝑐𝑖 and the chosen path runs from subclass 𝐾′ to superclass 𝐾, write 𝜋𝐾,𝐾′:𝐾′𝐷(𝐴)→𝐾𝐷(𝐴) for its dictionary projection. The effective candidate’s builder is 𝑏𝑖𝐾¯𝑑=𝜋𝐾,𝐾′(𝑐𝑖¯𝑑). For the empty path, 𝜋𝐾,𝐾 is the identity. For the displayed product representation of 𝖮𝗋𝖽𝐷, the abstract projection 𝜋𝖤𝗊,𝖮𝗋𝖽 is the ordinary first projection 𝜋1. Thus 𝜋1𝗈𝗋𝖽𝖨𝗇𝗍 and 𝖾𝗊𝖫𝗂𝗌𝗍(𝜋1𝗈𝗋𝖽𝖨𝗇𝗍) are not additional resolution oracles: they are the two instance builders just declared.
An evidence telescopeΔ𝑃 maps each predicate in 𝑃 to one target variable. More generally, an evidence storeΨ maps distinct predicates to well-typed target evidence terms; a telescope induces the store 𝗌𝗍𝗈𝗋𝖾(Δ𝑃) which maps each key to its bound variable. The resolution selector𝖻𝖾𝗌𝗍Ψ(𝐾𝜏) is the partial function that returns the exact 𝐾𝜏 entry when it exists; otherwise it returns the projection along the shortest superclass path from a local 𝐾′𝜏 entry; equal-length candidates and paths are broken by the fixed class/path order; otherwise it is undefined. Separately, 𝗉𝗂𝖼𝗄C(𝐾𝜏)=(𝑃,𝑏) freshens and one-way-matches the unique effective candidate, when one exists, and returns its premises and evidence builder 𝑏:Δ𝑃⇒𝖾𝐾𝐷(𝜏). Resolution constructs target evidence 𝑑 for a predicate 𝑝 from the candidate table and current evidence store; it is recorded by the judgment 𝗋𝖾𝗌𝗈𝗅𝗏𝖾C,Ψ(𝑝)=𝑑. Resolution first uses the selected local evidence 𝖻𝖾𝗌𝗍Ψ(𝐾𝜏)=𝑑. If none exists, it chooses the unique least effective-table clause and applies its builder to recursively resolved premise evidence. The two cases are 𝖻𝖾𝗌𝗍Ψ(𝐾𝜏)=𝑑𝗋𝖾𝗌𝗈𝗅𝗏𝖾C,Ψ(𝐾𝜏)=𝑑E−Local𝖻𝖾𝗌𝗍Ψ(𝐾𝜏)↑𝗉𝗂𝖼𝗄C(𝐾𝜏)=(𝑃,𝑏)𝗋𝖾𝗌𝗈𝗅𝗏𝖾C,Ψ(𝑝)=𝑑𝑝(𝑝∈𝑃)𝗋𝖾𝗌𝗈𝗅𝗏𝖾C,Ψ(𝐾𝜏)=𝑏¯𝑑𝑝E−Instance. Here a premise-free instance constructor is a constant. The premise 𝗉𝗂𝖼𝗄 in E-Instance means: choose the unique matching member of I↑, freshen its primitive scheme, compute the one-way matcher 𝜏0[𝜃]=𝜏, and put 𝑃=𝑃0[𝜃]. It is not symmetric unification. All uses of entailment below use this relation. Priority is only exact-local before superclass-local before the unique global candidate; the canonical superclass path was already fixed when the table was closed. Immediately, if 𝑑𝑜:𝖮𝗋𝖽𝐷(𝖨𝗇𝗍)∈Ψ, then 𝖻𝖾𝗌𝗍Ψ(𝖤𝗊𝖨𝗇𝗍)=𝜋1𝑑𝑜𝗋𝖾𝗌𝗈𝗅𝗏𝖾C0,Ψ(𝖤𝗊𝖨𝗇𝗍)=𝜋1𝑑𝑜E−Local. This example is a lookup in a general evidence store, such as the store built internally by normalization; it is not claiming that the canonical telescope Δ𝑃 contains a constructor-headed predicate. With no local evidence, instance resolution instead derives 𝖻𝖾𝗌𝗍∅(𝖤𝗊(𝖫𝗂𝗌𝗍𝖨𝗇𝗍))↑𝗉𝗂𝖼𝗄C0(𝖤𝗊(𝖫𝗂𝗌𝗍𝖨𝗇𝗍))=({𝖤𝗊𝖨𝗇𝗍},𝖾𝗊𝖫𝗂𝗌𝗍)𝖻𝖾𝗌𝗍∅(𝖤𝗊𝖨𝗇𝗍)↑𝗉𝗂𝖼𝗄C0(𝖤𝗊𝖨𝗇𝗍)=(∅,𝜋1𝗈𝗋𝖽𝖨𝗇𝗍){𝗋𝖾𝗌𝗈𝗅𝗏𝖾C0,∅(𝑝)=𝑑𝑝∣𝑝∈∅}=∅𝗋𝖾𝗌𝗈𝗅𝗏𝖾C0,∅(𝖤𝗊𝖨𝗇𝗍)=𝜋1𝗈𝗋𝖽𝖨𝗇𝗍E−Instance𝗋𝖾𝗌𝗈𝗅𝗏𝖾C0,∅(𝖤𝗊(𝖫𝗂𝗌𝗍𝖨𝗇𝗍))=𝖾𝗊𝖫𝗂𝗌𝗍(𝜋1𝗈𝗋𝖽𝖨𝗇𝗍)E−Instance. For sets, write C;𝑃⊩𝑄 when selected resolution constructs evidence for every 𝑞∈𝑄 under fresh dictionary variables for 𝑃.
For an admissible C, resolution terminates. For fixed C,Ψ,𝑝, it returns at most one evidence term up to alpha-renaming, and that term has target type 𝑝𝐷.
Proof of Lemma 11.1 — Resolution terminates and is functional
Proof. Every recursive resolution call is an effective-instance-premise call. Its type is a proper subterm of the matched head because superclass closure changes only the result class and evidence builder, never the primitive premises. Type size therefore decreases strictly. The selector 𝖻𝖾𝗌𝗍Ψ computes a superclass path by a finite scan of the finite acyclic hierarchy; it does not make a recursive resolution call. Hence neither phase admits an infinite call chain.
For functionality, 𝖻𝖾𝗌𝗍Ψ is a partial function: exact lookup is unique because Ψ has distinct keys, and the fixed length/class/path order selects one superclass projection. Its definedness also makes E-Local and E-Instance mutually exclusive. Otherwise 𝗉𝗂𝖼𝗄C is a partial function because the fully closed effective heads do not unify. One-way matching is preserved by type substitution. The induction hypotheses uniquely determine all premise evidence. Evidence typing follows in the same induction: a projection has the declared superclass dictionary type, and each effective builder is a well-typed projection of a primitive instance constructor consuming exactly its premise dictionaries. ◻
★★☆ Derive evidence for 𝖤𝗊(𝖫𝗂𝗌𝗍(𝖫𝗂𝗌𝗍𝖨𝗇𝗍)). Then show why allowing both 𝖤𝗊𝛼⇒𝖤𝗊(𝖫𝗂𝗌𝗍𝛼) and a second unifiable effective head violates admission. Explain why a primitive 𝖤𝗊𝖨𝗇𝗍 clause and the derived projection of 𝖮𝗋𝖽𝖨𝗇𝗍 are therefore rejected together.
Canonical predicate normalization is the deterministic admission procedure that processes ready class requests in a fixed priority order and records their evidence, not an unspecified rewrite system. For a class 𝐾, let 𝖽𝖾𝗉𝗍𝗁(𝐾) be the length of a longest path from 𝐾 to a root of the finite superclass DAG; thus a subclass has greater depth than its superclass. Fix a total order on class names and a lexicographic order on types obtained from a fixed constructor order, with bound variables compared by de Bruijn index. The request priority first decreases 𝖽𝖾𝗉𝗍𝗁, then uses those two orders.
The agenda is one finite priority queue of ready requests plus suspended constructor frames. Premises from every frame enter the same queue as unrelated requests; a frame contributes no evidence to the store until all its premises have returned evidence. To normalize a finite set 𝑃, put its requests on this agenda and start with an empty evidence store Ψ. Repeatedly remove the first request 𝑝 and perform exactly one of these actions:
if 𝖻𝖾𝗌𝗍Ψ(𝑝)=𝑑, record 𝑑 for this occurrence;
if 𝑝=𝐾𝛼 and the selector is undefined, allocate one fresh hole 𝑑𝑝:𝑝𝐷, add it to Ψ, and record 𝑑𝑝;
if 𝑝=𝐾(𝐶¯𝜏) and the selector is undefined, compute 𝗉𝗂𝖼𝗄C(𝑝)=(𝑅,𝑏). Put 𝑅 on the same agenda, together with a pending constructor frame. Once those premises have evidence, assemble 𝑏¯𝑑, add that evidence for 𝑝 to Ψ, and discharge the frame; or
if the last case has no effective candidate, return 𝗋𝖾𝗃𝖾𝖼𝗍(𝑝).
The printed order of an instance orders siblings in its frame; the fixed priority orders every ready request. Duplicate requests share the first recorded evidence. In particular, processing 𝖮𝗋𝖽𝖨𝗇𝗍 constructs and installs its dictionary before 𝖤𝗊𝖨𝗇𝗍 is considered, so the latter uses its superclass projection rather than demanding an independent construction. When the agenda empties, repeatedly remove a hole projected from a retained subclass hole and substitute that projection throughout the recorded evidence. Each cleanup pass removes at least one hole, so iteration reaches a fixed point. Then sort the remaining holes by the fixed syntax order. This defines the total result 𝗇𝖿C(𝑃)∈{𝗋𝖾𝗃𝖾𝖼𝗍(𝑝)}∪{𝗈𝗄(𝑄,𝜂)}. The evidence template 𝜂 maps every request in 𝑃 to a dictionary term over fresh holes for 𝑄. Evidence installed internally by a completed constructor frame is available to later requests, but a source predicate set never contributes a constructor-headed local assumption: such predicates are agenda goals. For example, 𝗇𝖿C0({𝖤𝗊(𝖫𝗂𝗌𝗍𝛼),𝖤𝗊𝛼,𝖮𝗋𝖽𝛼})=𝗈𝗄({𝖮𝗋𝖽𝛼},𝜂), and 𝜂 reconstructs the first two dictionaries using 𝖾𝗊𝖫𝗂𝗌𝗍(𝜋1𝑑𝑜) and 𝜋1𝑑𝑜.
Let 𝐹 be the completed, ordered frame forest recorded by one successful run of definition 13.3. For a substitution 𝑆, 𝗋𝖾𝗉𝗅𝖺𝗒𝐹[𝑆](𝑝[𝑆]) is the evidence obtained by rerunning the same agenda on the substituted requests, with the fixed request priority and the first-recorded duplicate policy of definition 13.3, while selecting local projections and effective clauses afresh. A former variable-headed hole that becomes constructor-headed is therefore expanded by the selected effective clause; two holes identified by 𝑆 reuse one store entry. Replay is partial exactly when this rerun reaches a constructor-headed request having no effective candidate.
Write 𝖲𝗈𝗅C(𝑃) when the closed set 𝑃 has a joint evidence construction: process it in decreasing superclass depth and fixed syntax order, resolving through the selected effective table and extending the local context after each success. Thus an 𝖮𝗋𝖽 dictionary constructed first may provide the 𝖤𝗊 dictionary required by the same set. Two open requirement sets are ground-equivalent when every grounding substitution 𝜃 satisfies 𝖲𝗈𝗅C(𝑃[𝜃])⟺𝖲𝗈𝗅C(𝑄[𝜃]).
A source predicate set contributes only variable-headed holes. A constructor-headed request must be decomposed through the selected effective instance; it may not be assumed as local evidence. This is the canonical-local-evidence policy enforced by canonicalization and resolution.
For every finite 𝑃, 𝗇𝖿C(𝑃) returns exactly one result. If it returns 𝗈𝗄(𝑄,𝜂), then 𝑄 is variable-headed and canonical, C;𝑄⊩𝑃, 𝑃 and 𝑄 are ground-equivalent, and no proper subset of 𝑄 entails 𝑄. More precisely, for every type substitution 𝑆, 𝗇𝖿C(𝑃[𝑆]) and 𝗇𝖿C(𝑄[𝑆]) either reject together or return the same canonical set 𝑅; on success the template for 𝑃[𝑆] is alpha-equivalent to the composite of the template for 𝑄[𝑆] with 𝜂[𝑆]. If normalization returns 𝗋𝖾𝗃𝖾𝖼𝗍(𝑝), the displayed constructor-headed request has no selected derivation under the effective table and the canonical-local-evidence policy.
Proof.Termination and determinism. Every premise placed below a constructor frame has a proper-subterm type, so frame depth is bounded by the size of its root request. The initial set and every premise list are finite; consequently the agenda is finite. Nonunifiability of the fully closed effective heads gives one candidate and matcher. The fixed agenda and sibling orders remove every remaining choice. Thus the procedure returns one success or the first fixed-priority rejection.
Replay soundness. Induct on the height of the finite completed-frame tree, visiting children before their parent. If a completed frame 𝐹 has retained holes 𝑄𝐹, the induction property is: for every request 𝑝 in the subtree rooted at 𝐹 there is a selected term Δ𝑄𝐹⊢𝜂𝐹(𝑝):𝑝𝐷,𝜂𝐹(𝑝)[𝑆][¯𝑑/𝑄𝐹[𝑆]]=𝛼𝗋𝖾𝗉𝗅𝖺𝗒𝐹[𝑆](𝑝[𝑆]). Applying 𝑆 and replacing each substituted hole by its recorded evidence therefore gives exactly the replayed evidence. The property is simultaneous for all recorded requests. A fresh variable-headed hole is its own evidence. A completed constructor frame is derivable from its recorded premise evidence; installing it in Ψ merely shares that derivation with later goals. In the superclass case, suppose the selected effective clause comes from 𝑖:𝑃⇒𝐾′(𝐶¯𝜏) and path projection 𝜋𝐾,𝐾′. For premise evidence ¯𝑑, both direct replay and replay after substitution construct 𝜋𝐾,𝐾′(𝑖¯𝑑):𝐾𝐷(𝐶¯𝜏). Effective nonoverlap is stable under substitution, so replay cannot change the selected clause. Duplicate sharing preserves the conjunction, and superclass-hole removal preserves it because a retained subclass dictionary projects to the removed superclass dictionary. Composing the recorded builders and projections gives 𝜂 and proves C;𝑄⊩𝑃.
Naturality. For naturality, induct simultaneously on the two replay trees for 𝑃[𝑆] and 𝑄[𝑆], using the maximum remaining height. A substituted variable-headed hole either remains a hole or becomes a constructor request; in the latter case both runs select the same effective clause. A constructor frame replays that clause and applies the induction hypotheses to its proper-subterm premises. If substitution merges two formerly distinct holes, duplicate sharing maps both occurrences to the first recorded evidence, so no lockstep bijection between old holes is required. Finally, if one substituted hole becomes a superclass consequence of another, the fixed projection replaces it on both runs. When the subclass dictionary is 𝑖¯𝑑, both runs record 𝜋𝐾,𝐾′(𝑖¯𝑑) from the same primitive premises. These cases also show that a missing constructor candidate occurs on both sides. Hence both runs reject together or finish with the same ordered holes 𝑅, and their evidence templates commute as stated. With a grounding substitution and empty evidence context, this is ground equivalence.
Irredundancy and rejection. At the end, distinct members of 𝑄 are variable-headed and no member is a superclass consequence of the others. Effective instances cannot match a variable-headed request. Therefore removing any member leaves that request underivable from the remainder. In the rejection case, the absence of a selected effective constructor-headed candidate leaves neither a global derivation nor an admissible constructor-headed local assumption. ◻
Proof. Fix selected entailment derivations of every root request in 𝑃[𝑆] from 𝑅0. Descend each completed frame tree from its root toward its retained holes, inducting on the maximum remaining frame height. At a constructor frame, the root request cannot be discharged by an exact entry of the canonical set 𝑅0, whose entries are variable headed. If it were discharged by a superclass projection from such an entry, its head would still be variable headed. Its selected derivation must therefore use an effective instance clause. Nonoverlap forces that clause to be the one recorded in the frame; invert the selected derivation to obtain selected derivations of the proper-subterm premises, and continue downward. At a retained hole, the selected derivation reached by this inversion is evidence for the corresponding member of 𝑄[𝑆]. If 𝑆 identifies two holes, duplicate sharing keeps the first selected derivation and directs both occurrences to it. Every retained hole is therefore entailed by 𝑅0, which is the displayed entailment. ◻
Without superclass closure, naturality and canonical factorization are false. Let 𝖮𝗋𝖽 have superclass 𝖤𝗊 and take only the primitive instances 𝖮𝗋𝖽𝖨𝗇𝗍,𝖮𝗋𝖽𝛼⇒𝖮𝗋𝖽(𝖫𝗂𝗌𝗍𝛼). Normalizing {𝖮𝗋𝖽(𝖫𝗂𝗌𝗍𝛼),𝖤𝗊𝛽} without the derived projected clause retains {𝖮𝗋𝖽𝛼,𝖤𝗊𝛽}. After 𝛼:=𝖨𝗇𝗍 and 𝛽:=𝖫𝗂𝗌𝗍𝖨𝗇𝗍, the original set is jointly solvable by constructing 𝖮𝗋𝖽(𝖫𝗂𝗌𝗍𝖨𝗇𝗍) and projecting, while the retained set is not. In I↑ the derived clause 𝖮𝗋𝖽𝛼⇒𝖤𝗊(𝖫𝗂𝗌𝗍𝛼) builds the missing projection, so both sides succeed.
Let 𝖿𝗍𝗏 denote free type variables. Given Γ, 𝑃, and 𝜏, first compute 𝗇𝖿C(𝑃). If it rejects, generalization rejects at the same request; in particular, 𝖲𝗁𝗈𝗐𝖡𝗈𝗈𝗅 cannot become a silent residual. Otherwise let the result be 𝗈𝗄(𝑃0,𝜂) and put 𝐴=𝖿𝗍𝗏(𝑃0,𝜏)∖𝖿𝗍𝗏(Γ). Every member of 𝑃0 has the form 𝐾𝛼, so place it in 𝑃𝑔 when 𝛼∈𝐴 and in 𝑃𝑟 otherwise. This gives the disjoint, exhaustive split 𝑃0=𝑃𝑔⊎𝑃𝑟. Define 𝗇𝖿C(𝑃𝑔)=𝗈𝗄(𝑄,𝜂𝑔),𝖦𝖾𝗇C(Γ;𝑃;𝜏)=(𝑃𝑟,∀𝐴.𝑄⇒𝜏,𝜁). Because 𝑃𝑔 is a subset of the already canonical variable-headed set 𝑃0, this second normalization returns 𝑄=𝑃𝑔 and the identity template. It is retained deliberately so every generalization boundary calls the same checked interface, rather than relying on an unchecked invariant in an implementation. Here 𝜁 composes the two normalization templates and witnesses C;𝑃𝑟,𝑄⊩𝑃. The residual 𝑃𝑟 remains at the enclosing binding. A scheme is unambiguous when 𝖿𝗍𝗏(𝑄)⊆𝖿𝗍𝗏(𝜏). Thus the first scheme below is rejected because its result does not determine 𝐴; the second is unambiguous: ∀𝐴.𝖲𝗁𝗈𝗐𝐴⇒𝖲𝗍𝗋𝗂𝗇𝗀,∀𝐴.𝖤𝗊𝐴⇒𝐴→𝖡𝗈𝗈𝗅. The final step of 𝖦𝖾𝗇C checks this inclusion and rejects the binding when it fails.
★☆☆ Explain why explicit type application could run the ambiguous scheme above, but implicit use cannot select it coherently. Give two distinct target values of type 𝖲𝗁𝗈𝗐𝐷(𝖨𝗇𝗍), such as decimal and hexadecimal printers, that expose the difference; they need not be admissible source instances in C0.
Canonicality is checked when a binding enters an environment; it is not a claim that raw textual substitution preserves a predicate list. We use the global postfix action 𝜏[𝑆] and left-to-right composition 𝑆;𝑇, characterized by 𝜏[𝑆;𝑇]=𝜏[𝑆][𝑇]. Define the canonical action𝑆⋆Γ pointwise. Freshen a binding 𝑥:∀¯𝑎.𝑃⇒𝜏 away from 𝑆, apply 𝑆 only to its free variables, and compute 𝗇𝖿C(𝑃[𝑆])=𝗈𝗄(𝑄,𝜅𝑥). The resulting binding is 𝑥:∀¯𝑎.𝑄⇒𝜏[𝑆], annotated by the transport 𝜅𝑥:Δ𝑄⇒𝖾Δ𝑃[𝑆]. The action is undefined if normalization or the ambiguity check rejects. For example, specializing 𝑥:𝖤𝗊𝛼⇒𝛼→𝖡𝗈𝗈𝗅 at 𝛼:=𝖨𝗇𝗍 removes the predicate and records the global Eq Int evidence projected from Ord Int; it does not leave a noncanonical ground predicate in the environment. One wants 𝑇⋆𝑆⋆Γ and 𝑆;𝑇⋆Γ the same intended composite, but determinism alone does not prove that claim. We use 𝑆⋆Γ only when this action succeeds. Its target translation (𝑆⋆Γ)𝐷 retains the substituted prior interface 𝑃[𝑆]⇒𝜏[𝑆] for each free target variable; 𝜅𝑥 converts evidence for the canonical source view 𝑄 to that interface at each use.
Whenever the displayed actions are defined, 𝑇⋆𝑆⋆Γ=𝑆;𝑇⋆Γ up to fresh binders. The accumulated evidence annotation on the left is alpha-equivalent to the transport recorded on the right.
Proof of Lemma 13.9 — Canonical environment actions compose
Proof. Work bindingwise after one common freshening of its quantified variables. If normalizing 𝑃[𝑆] yields 𝑄 with transport 𝜅, the substitution clause of lemma 11.2 says that normalizing 𝑄[𝑇] and normalizing 𝑃[𝑆;𝑇] return the same canonical predicate set. Its commuting template clause equates the sequential transport with the direct transport. Ordinary type components agree because substitution composes. Repeating this argument over the finite environment proves the result; the ambiguity checks inspect the same final scheme and therefore agree as well. ◻
Qualified typing and inference
The source term grammar is the HM grammar. Its declarative judgment is C;𝑃;Γ⊢𝑒:𝜏. It is formed only when 𝗇𝖿C(𝑃)=𝗈𝗄(𝑃,𝗂𝖽) and each scheme was admitted canonically and unambiguously when its binding entered Γ. Subsequent type substitution acts through 𝑆⋆Γ, not by raw substitution, using convention 13.6. The structural rules for variables, abstractions, applications, and let are as follows. 𝑥:𝜎∈Γ𝜎≽(𝑄⇒𝜏)C;𝑃⊩𝑄C;𝑃;Γ⊢𝑥:𝜏Q−VarC;𝑃;Γ,𝑥:𝜏1⊢𝑒:𝜏2C;𝑃;Γ⊢𝜆𝑥.𝑒:𝜏1→𝜏2Q−LamC;𝑃1;Γ⊢𝑒1:𝜏1→𝜏2C;𝑃2;Γ⊢𝑒2:𝜏1𝗇𝖿C(𝑃1∪𝑃2)=𝗈𝗄(𝑃,𝜂)C;𝑃;Γ⊢𝑒1𝑒2:𝜏2Q−AppC;𝑃1;Γ⊢𝑒1:𝜏1𝖦𝖾𝗇C(Γ;𝑃1;𝜏1)=(𝑃𝑟,𝜎,𝜁)C;𝑃2;Γ,𝑥:𝜎⊢𝑒2:𝜏2𝗇𝖿C(𝑃𝑟∪𝑃2)=𝗈𝗄(𝑃,𝜂)C;𝑃;Γ⊢𝐥𝐞𝐭𝑥=𝑒1𝐢𝐧𝑒2:𝜏2Q−Let. In Q-Var, 𝜎≽(𝑄⇒𝜏) means instantiate the quantified variables and then discharge the instantiated scheme predicates from 𝑄. Thus this chapter-local occurrence has a qualified type on the right, unlike the HM monotype-instance relation of chapter 3. The three-place occurrence C;𝑃⊩𝑄 is likewise the class-environment-indexed evidence relation defined above, not the two-place row entailment. For a concrete derivation, take Γ0(𝖾𝗊)=∀𝛼.𝖤𝗊𝛼⇒𝛼→𝛼→𝖡𝗈𝗈𝗅. Identify a monotype 𝛼 in Γ with the scheme ∀∅.∅⇒𝛼. Then the first new judgment is exercised in full: Γ0(𝖾𝗊)=∀𝛽.𝖤𝗊𝛽⇒𝛽→𝛽→𝖡𝗈𝗈𝗅(𝖤𝗊𝛽⇒𝛽→𝛽→𝖡𝗈𝗈𝗅)[𝛼/𝛽]=𝖤𝗊𝛼⇒𝛼→𝛼→𝖡𝗈𝗈𝗅C0;{𝖤𝗊𝛼}⊩{𝖤𝗊𝛼}C0;{𝖤𝗊𝛼};Γ0,𝑥:𝛼⊢𝖾𝗊:𝛼→𝛼→𝖡𝗈𝗈𝗅Q−Var𝑥:(∅⇒𝛼)∈Γ0,𝑥:𝛼C0;∅⊩∅C0;∅;Γ0,𝑥:𝛼⊢𝑥:𝛼Q−VarC0;{𝖤𝗊𝛼};Γ0,𝑥:𝛼⊢𝖾𝗊𝑥:𝛼→𝖡𝗈𝗈𝗅Q−App𝑥:(∅⇒𝛼)∈Γ0,𝑥:𝛼C0;∅⊩∅C0;∅;Γ0,𝑥:𝛼⊢𝑥:𝛼Q−VarC0;{𝖤𝗊𝛼};Γ0,𝑥:𝛼⊢𝖾𝗊𝑥𝑥:𝖡𝗈𝗈𝗅Q−AppC0;{𝖤𝗊𝛼};Γ0⊢𝜆𝑥.𝖾𝗊𝑥𝑥:𝛼→𝖡𝗈𝗈𝗅Q−Lam.
Qualified Algorithm W
Qualified inference returns predicates as well as an HM substitution and type: 𝑊C(Γ,𝑒)=(𝑃,𝑆,𝜏). It uses the same most-general unifier as chapter 3. Its clauses use the postfix action and left-to-right composition fixed above. The brackets 𝐴[𝐵/𝛼] still denote one capture-avoiding substitution. Write 𝖼𝗇𝖿C(𝑃)=𝑄 when 𝗇𝖿C(𝑃)=𝗈𝗄(𝑄,𝜂) for the uniquely determined 𝜂; if normalization rejects, W rejects at that clause. The mathematical W triple discards 𝜂; its derivation records the normalization call, and the elaborator below recomputes the unique template.
For 𝑥, fresh-instantiate Γ(𝑥)=∀¯𝛼.𝑄⇒𝜏 to (𝑄′,𝜏′) and return (𝖼𝗇𝖿C(𝑄′),𝗂𝖽,𝜏′).
For 𝜆𝑥.𝑒, choose fresh 𝑎, compute 𝑊C(Γ,𝑥:𝑎,𝑒)=(𝑃,𝑆,𝜏), and return (𝑃,𝑆,𝑎[𝑆]→𝜏).
For 𝑒1𝑒2, compute (𝑃1,𝑆1,𝜏1) for 𝑒1, then (𝑃2,𝑆2,𝜏2) for 𝑒2 in 𝑆1⋆Γ. With fresh 𝑎, let 𝑈=𝗆𝗀𝗎(𝜏1[𝑆2],𝜏2→𝑎) and return (𝖼𝗇𝖿C((𝑃1[𝑆2]∪𝑃2)[𝑈]),𝑆1;𝑆2;𝑈,𝑎[𝑈]).
For 𝐥𝐞𝐭𝑥=𝑒1𝐢𝐧𝑒2, compute (𝑃1,𝑆1,𝜏1), then 𝖦𝖾𝗇C(𝑆1⋆Γ;𝑃1;𝜏1)=(𝑃𝑟,𝜎,𝜁), and (𝑃2,𝑆2,𝜏2) for 𝑒2 in 𝑆1⋆Γ,𝑥:𝜎. Return (𝖼𝗇𝖿C(𝑃𝑟[𝑆2]∪𝑃2),𝑆1;𝑆2,𝜏2).
The earlier example follows the first three clauses: eq contributes 𝖤𝗊𝑎⇒𝑎→𝑎→𝖡𝗈𝗈𝗅; each occurrence of x unifies with 𝑎; canonicalization leaves {𝖤𝗊𝑎}; abstraction returns 𝖤𝗊𝑎⇒𝑎→𝖡𝗈𝗈𝗅.
Proof of Lemma 11.3 — The generalization split is maximal
Proof. The set 𝐴 contains exactly the variables not fixed by Γ. Successful normalization leaves only variable-headed requirements, removing the empty-variable case. Hence every residual is exactly 𝐾𝛼, with 𝛼∈𝐴 or 𝛼∈𝖿𝗍𝗏(Γ). The two comprehensions are therefore disjoint, exhaustive, and forced. ◻
Proof of Lemma 13.11 — Declarative typing is stable under canonical substitution
Proof. Induct on the displayed typing derivation. In Q-Var, substitute the scheme instance and its selected entailment. Naturality of lemma 11.2 and lemma 13.8 replace the substituted predicate lists by their canonical forms. The abstraction case extends the canonical action by 𝑥:𝜏1[𝑆]. In Q-App, apply the induction hypotheses to both premises and normalize the union; naturality identifies this result with 𝑄. In Q-Let, apply the first induction hypothesis, then canonicalize and factor its generalized predicate list to rebuild the substituted scheme. Apply the second induction hypothesis under that scheme, canonicalize the residual list, and use naturality to identify the combined normal form with 𝑄; Q-Let then rebuilds the conclusion. Freshening the quantified variables away from 𝑆 preserves the free-variable side condition. These are all four rules. ◻
Proof. By induction on 𝑒. For a variable, fresh instantiation and canonicalization give exactly Q-Var. For an abstraction, the induction hypothesis types the body under 𝑆⋆Γ,𝑥:𝑎[𝑆]; Q-Lam discharges 𝑥. For an application, apply lemma 13.11 with 𝑈 to both induction hypotheses. The MGU equation 𝜏1[𝑆2][𝑈]=(𝜏2→𝑎)[𝑈] says both operands have the common domain 𝜏2[𝑈]; Q-App combines the transported predicates. For let, the induction hypothesis for 𝑒1 and lemma 11.3 justify the exact scheme and residual predicates used by Q-Let; the second induction hypothesis types 𝑒2, and final canonicalization combines 𝑃𝑟[𝑆2] with 𝑃2. ◻
Say that 𝑄⇒𝜌 is a qualified instance of 𝑃⇒𝜏 when some substitution 𝑇 satisfies 𝜏[𝑇]=𝜌 and C;𝑄⊩𝑃[𝑇].
Suppose every canonical environment action, normalization, and ambiguity check succeeds. If C;𝑄;𝑅⋆Γ⊢𝑒:𝜌, then W succeeds with (𝑃,𝑆,𝜏), and there is a 𝑇 such that 𝜏[𝑇]=𝜌,𝑇⋆𝑆⋆Γ=𝑅⋆Γ,C;𝑄⊩𝑃[𝑇]. Consequently the unambiguous closed scheme obtained by generalizing W’s answer is principal among the schemes admitted by QTC0.
Proof of Theorem 11.5 — Success and principality for QTC_0
Proof. Induct on the declarative typing derivation, generalized over the base environment Γ and its action 𝑅. The induction claim includes success: W terminates at the corresponding syntax and returns (𝑃,𝑆,𝜏); there is then a substitution 𝑇 satisfying all three displayed conclusions. Thus an induction hypothesis licenses the next recursive call rather than assuming that call has returned.
Canonicalization needs a direction not carried by its output template. If W normalizes an input predicate set 𝑃in to 𝑃, the template gives 𝑃⊩𝑃in. Principality instead needs to derive 𝑃[𝑇] from a declarative entailment of 𝑃in[𝑇]. Every use below of a final normalization therefore invokes lemma 13.8.
Variable. Fresh instantiation always returns. Rename its variables away from the declarative instance. The substitution witnessing the declarative instance factors through that fresh renaming; canonical factorization proves the returned predicate entailment. Its restriction to the environment variables is 𝑅, so the canonical environments agree.
Abstraction. The premise induction hypothesis makes the body call succeed. Extend its factor by sending W’s fresh argument variable to the declarative domain. This gives the arrow equality, leaves the predicate entailment unchanged, and the extended canonical-environment equation discharges the bound variable.
Application. Inversion gives premise types 𝐵→𝜌 and 𝐵. The two induction hypotheses make W’s calls return (𝑃1,𝑆1,𝜏1) and (𝑃2,𝑆2,𝜏2). The ordinary HM factorization-extension calculation of lemma 4.45 aligns their residual substitutions on the variables inherited from Γ. Extend the aligned substitution to W’s fresh result variable 𝑎 by 𝑎↦𝜌; call the result 𝑉. Then 𝜏1[𝑆2][𝑉]=(𝜏2→𝑎)[𝑉]=𝐵→𝜌. Hence W’s unification call succeeds. Most-generality gives a 𝑇 such that, on every variable in this equation and in the inherited environment, 𝑉=𝑈;𝑇,𝑎[𝑈][𝑇]=𝜌,𝑇⋆𝑆1;𝑆2;𝑈⋆Γ=𝑅⋆Γ. The two premise entailments, transported through this equality, give C;𝑄⊩(𝑃1[𝑆2]∪𝑃2)[𝑈][𝑇]. Canonical factorization for W’s final normalization gives C;𝑄⊩𝑃[𝑇].
Let. The first induction hypothesis makes the right-hand-side call return (𝑃1,𝑆1,𝜏1). Write its deterministic split as 𝑋=ftv(𝑃1,𝜏1)∖ftv(𝑆1⋆Γ),𝑃1=𝑃𝗀1∪𝑃𝗋1,𝜎=∀𝑋.𝑃𝗀1⇒𝜏1. By lemma 11.3, the declarative generalized scheme factors through 𝜎, while 𝑃𝗋1 remains an outer requirement. After extending both equal canonical environments by the factored scheme, the body induction hypothesis makes the second call return (𝑃2,𝑆2,𝜏2). The HM factorization-extension lemma extends the body factor on variables generalized at the first call; let 𝑇 be the resulting common factor. Then 𝜏2[𝑇]=𝜌,𝑇⋆𝑆1;𝑆2⋆Γ=𝑅⋆Γ,C;𝑄⊩(𝑃𝗋1[𝑆2]∪𝑃2)[𝑇]. Canonical factorization for the last normalization yields C;𝑄⊩𝑃[𝑇].
Every recursive and unification call has now been shown to succeed. A normalization rejection contradicts the corresponding declarative entailment by canonical factorization. For a closed term, generalization quantifies every free result variable, and the factorization just proved is qualified-scheme generality. ◻
The theorem does not cover ambiguous schemes, overlapping effective heads, higher-rank annotations, or defaulting. It also assumes the usual completeness and most-generality theorem for the HM unifier rather than reproving it.
★★☆ Run W on 𝜆𝑥.𝖾𝗊(𝖼𝗈𝗇𝗌𝑥𝗇𝗂𝗅)(𝖼𝗈𝗇𝗌𝑥𝗇𝗂𝗅), using the usual polymorphic list constructor schemes. Record the instance decomposition that turns 𝖤𝗊(𝖫𝗂𝗌𝗍𝑎) into 𝖤𝗊𝑎. Then give a let right-hand side whose normalization reaches the missing ground request 𝖲𝗁𝗈𝗐𝖡𝗈𝗈𝗅 and is therefore rejected.
The evidence target 𝑈 extends the Church-style constructor and term core of definition 7.6. The inherited fragment has type, term, and let abstraction/application, products, and the declared base types. Its terms and the dictionary delta are 𝑢::=𝑥∣𝜆𝑥:𝑇.𝑢∣𝑢1𝑢2∣𝐥𝐞𝐭𝑥=𝑢1𝐢𝐧𝑢2∣Λ𝛼.𝑢∣𝑢[𝑇]∣𝜆{𝑑:𝐷}.𝑢∣𝑢{𝛿}∣𝑐𝑖∣𝜋𝐾,𝐾′𝑢. The inherited typing rules are exactly those of that core, extended homomorphically by let and products. The new typing rules are
Γ,𝑑:𝐷⊢𝑢:𝑇
Γ⊢𝜆{𝑑:𝐷}.𝑢:𝐷→𝑇
U-DictLam
Γ⊢𝑢:𝐷→𝑇Γ⊢𝛿:𝐷
Γ⊢𝑢{𝛿}:𝑇
U-DictApp
Each 𝑐𝑖 and 𝜋𝐾,𝐾′ has the closed polymorphic type declared below.
Values are base values, ordinary and type abstractions, dictionary abstractions, product pairs of values, and saturated dictionary constructors whose arguments are values. Evaluation contexts are generated by 𝐸::=[]∣𝐸𝑢∣𝑣𝐸∣𝐥𝐞𝐭𝑥=𝐸𝐢𝐧𝑢∣𝐸[𝑇]∣𝐸{𝑢}∣𝑣{𝐸}∣𝜋𝐾,𝐾′𝐸, together with the left-to-right product and declared base-operation contexts. The root contractions are (𝜆𝑥:𝑇.𝑢)𝑣⟶𝑢[𝑣/𝑥],(Λ𝛼.𝑢)[𝑇]⟶𝑢[𝑇/𝛼],𝐥𝐞𝐭𝑥=𝑣𝐢𝐧𝑢⟶𝑢[𝑣/𝑥],(𝜆{𝑑:𝐷}.𝑢){𝛿}⟶𝑢[𝛿/𝑑]. A target signature may additionally declare a finite set of deterministic root equations for saturated base and dictionary constructors. Every such equation is checked once as Γ⊢𝑙:𝑇 and Γ⊢𝑟:𝑇 with the same free variables; superclass projection is one such equation. This well-typed-equation condition is part of the admitted class environment and is the only premise about primitive computation used by target preservation. Thus dictionary constructors and projections are not left to an implicit collection of “standard” rules.
Write 𝜏𝐷 for source-type translation, Γ𝐷 for pointwise context translation, and 𝖣𝗂𝖼𝗍𝖳𝖾𝗅(𝑄) for the ordered dictionary telescope. The map erase(𝑢) erases dictionary braces from a target term and applies the corresponding erasure to every context or telescope entry.
The target signature is part of the admitted class environment. Each superclass edge and instance declaration contributes, respectively, 𝜋𝐾,𝐾′:∀𝛼.𝐾′𝐷(𝛼)→𝐾𝐷(𝛼),𝑐𝑖:∀¯𝛼.(𝑝1)𝐷→⋯→(𝑝𝑚)𝐷→𝐾𝐷(𝐶¯𝜏)for𝑝1,…,𝑝𝑚⇒𝐾(𝐶¯𝜏). An effective candidate contributes no new primitive constant: its builder is the displayed primitive 𝑐𝑖 followed by its declared superclass projection. The method interface is explicit as well: 𝖾𝗊♯:∀𝛼.𝖤𝗊𝐷(𝛼)→𝛼→𝛼→𝖡𝗈𝗈𝗅,𝖾𝗊♯:=Λ𝛼.𝜆{𝑑:𝖤𝗊𝐷(𝛼)}.𝑑.
For canonical 𝑃, let Δ𝑃 be the ordered telescope 𝑑𝑝:𝑝𝐷. If an evidence template 𝜂 has domain 𝑅, write 𝜂⋅𝑢 for simultaneous replacement of the holes 𝑑𝑟 in 𝑢. A type substitution also acts on core type annotations, type applications, dictionary types, and evidence templates; write this action 𝑆†𝑣. Holes are keyed by their predicates, and 𝑆†𝑑𝑝=𝑑𝑝[𝑆]. The image telescope contains one binder for each distinct predicate in 𝑃[𝑆], in canonical order. Thus if 𝑝[𝑆]=𝑝′[𝑆], the two occurrences become references to the same binder rather than two colliding declarations. The following normalizer template then replaces those image holes by evidence over the canonical result telescope. The annotation on a binding in 𝑆⋆Γ remembers the template that converts dictionaries for its canonical predicates to dictionaries expected by the binding’s previous target interface. These annotations compose when −⋆− composes.
If Γ𝐷,Δ𝑃⊢𝑢:𝑇, then 𝑆†Γ𝐷,Δ𝑃[𝑆]⊢𝑆†𝑢:𝑆†𝑇, where Δ𝑃[𝑆] coalesces equal predicate keys. If normalization of 𝑃[𝑆] returns 𝗈𝗄(𝑄,𝜂), then 𝜂⋅𝑆†𝑢 is scoped under Δ𝑄.
Proof of Lemma 13.15 — Target substitution is scoped under merging
Proof. Induct on the target typing derivation. The hole case uses the key equation above; coalescing changes two declarations into repeated uses of their one common declaration. All type and term constructors are homomorphic. The second claim is simultaneous evidence substitution, using the typing of the normalizer template from lemma 11.2. ◻
Elaboration is indexed by the successful W derivation W: C;Δ𝑃;Γ⊢W𝐷𝑒:𝜏⇝𝑢. Here Γ is W’s input environment. The derivation W records W’s semantic result (𝑃,𝑆,𝜏): 𝑆 transports the input environment, 𝑃 is the residual predicate set, and 𝜏 is the inferred source type. The conclusion adds the elaborated target term 𝑢, typed under 𝑆⋆Γ and Δ𝑃. The elaboration judgment has cases for variables, abstractions, applications, and lets. A variable occurrence uses exactly the instantiation 𝜃 recorded by W. Its 𝜅𝑥 is the binding’s accumulated canonical-environment transport; it is the identity for a binding that has not been transported. For a template 𝜂 and a subset 𝑅 of its domain, 𝜂|𝑅 is the simultaneous evidence substitution restricted to holes whose keys lie in 𝑅. 𝑥:(∀¯𝛼.𝑄⇒𝜏0;𝜅𝑥)∈Γ𝗋𝖾𝗌𝗈𝗅𝗏𝖾C,𝗌𝗍𝗈𝗋𝖾(Δ𝑃)(𝑞[𝜃])=𝛿𝑞(𝑞∈𝑄)C;Δ𝑃;Γ⊢W𝐷𝑥:𝜏0[𝜃]⇝𝑥[¯𝛼[𝜃]]{(𝜃†𝜅𝑥)(¯𝛿𝑞)}D−Var𝑎fresh𝑊C(Γ,𝑥:𝑎,𝑒)=(𝑃,𝑆,𝜏)C;Δ𝑃;Γ,𝑥:𝑎⊢W0𝐷𝑒:𝜏⇝𝑢C;Δ𝑃;Γ⊢W𝐷𝜆𝑥.𝑒:𝑎[𝑆]→𝜏⇝𝜆𝑥:(𝑎[𝑆])𝐷.𝑢D−Lam𝑊C(Γ,𝑒1)=(𝑃1,𝑆1,𝜏1)C;Δ𝑃1;Γ⊢W1𝐷𝑒1:𝜏1⇝𝑢1𝑊C(𝑆1⋆Γ,𝑒2)=(𝑃2,𝑆2,𝜏2)C;Δ𝑃2;𝑆1⋆Γ⊢W2𝐷𝑒2:𝜏2⇝𝑢2𝑈=𝗆𝗀𝗎(𝜏1[𝑆2],𝜏2→𝑎)𝗇𝖿C((𝑃1[𝑆2]∪𝑃2)[𝑈])=𝗈𝗄(𝑃,𝜂)C;Δ𝑃;Γ⊢W𝐷𝑒1𝑒2:𝑎[𝑈]⇝(𝜂|𝑃1[𝑆2][𝑈]⋅𝑈†𝑆2†𝑢1)(𝜂|𝑃2[𝑈]⋅𝑈†𝑢2)D−App For let, generalization records a template 𝜁:Δ𝑃𝑟,Δ𝑄⇒𝖾Δ𝑃1 reconstructing the right-hand side requirements. After 𝑆2, if 𝜂:Δ𝑃⇒𝖾Δ𝑃𝑟[𝑆2],Δ𝑃2 is the final normalization template, write 𝜂𝑟,𝜂2 for its restrictions and put 𝑢𝗅𝖾𝗍:=𝐥𝐞𝐭𝑥=Λ¯𝑎.𝜆{¯𝑑𝑄:𝖣𝗂𝖼𝗍𝖳𝖾𝗅(𝑄)}.((𝜂𝑟∪𝗂𝖽𝑄)∘𝑆2†𝜁)⋅𝑆2†𝑢1𝐢𝐧𝜂2⋅𝑢2.𝑊C(Γ,𝑒1)=(𝑃1,𝑆1,𝜏1)C;Δ𝑃1;Γ⊢W1𝐷𝑒1:𝜏1⇝𝑢1𝖦𝖾𝗇C(𝑆1⋆Γ;𝑃1;𝜏1)=(𝑃𝑟,∀¯𝑎.𝑄⇒𝜏1,𝜁)𝑊C(𝑆1⋆Γ,𝑥:∀¯𝑎.𝑄⇒𝜏1,𝑒2)=(𝑃2,𝑆2,𝜏2)C;Δ𝑃2;𝑆1⋆Γ,𝑥:∀¯𝑎.𝑄⇒𝜏1⊢W2𝐷𝑒2:𝜏2⇝𝑢2𝗇𝖿C(𝑃𝑟[𝑆2]∪𝑃2)=𝗈𝗄(𝑃,𝜂)C;Δ𝑃;Γ⊢W𝐷𝐥𝐞𝐭𝑥=𝑒1𝐢𝐧𝑒2:𝜏2⇝𝑢𝗅𝖾𝗍D−Let For a nonidentity let transport, take 𝐥𝐞𝐭𝑓=𝜆𝑥𝑠.𝖾𝗊𝑥𝑠𝑥𝑠𝐢𝐧𝑓𝗇𝗂𝗅𝖨𝗇𝗍. The right-hand side initially requests 𝑃1={𝖤𝗊(𝖫𝗂𝗌𝗍𝑎)}. Generalization retains 𝑄={𝖤𝗊𝑎} and records the nonidentity template 𝜁(𝑑𝑎)=𝖾𝗊𝖫𝗂𝗌𝗍(𝑑𝑎):𝖤𝗊𝐷(𝖫𝗂𝗌𝗍𝑎). Consequently D-Let emits the generalized binding 𝐥𝐞𝐭𝑓=Λ𝑎.𝜆{𝑑𝑎}.𝜆𝑥𝑠.𝖾𝗊♯[𝖫𝗂𝗌𝗍𝑎]{𝖾𝗊𝖫𝗂𝗌𝗍(𝑑𝑎)}𝑥𝑠𝑥𝑠𝐢𝐧𝑓[𝖨𝗇𝗍]{𝜋1𝗈𝗋𝖽𝖨𝗇𝗍}𝗇𝗂𝗅𝖨𝗇𝗍. Here 𝜁 performs the instance decomposition and the body occurrence of 𝑓 uses the nontrivial instantiation recorded by D-Var.
Here 𝖣𝗂𝖼𝗍𝖳𝖾𝗅(𝑄) is the ordered telescope just defined. The mathematical W answer remains (𝑃,𝑆,𝜏); W stores its choices, while the unique 𝜂 and 𝜁 are recomputed by the total normalizer. In the application rule, 𝑆2 and 𝑈 act on 𝑃1,𝑢1, 𝑈 acts on 𝑃2,𝑢2, and 𝑆1⋆− acts on the argument environment. In the let rule, 𝑆2 acts on 𝑃𝑟,𝜁,𝑢1 before final canonicalization.
Top-level closure is a separate, deterministic operation. If 𝑊C(∅,𝑒)=(𝑃,𝑆,𝜏),𝖦𝖾𝗇C(∅;𝑃;𝜏)=(∅,∀¯𝑎.𝑄⇒𝜏,𝜁),C;Δ𝑃;∅⊢W𝐷𝑒:𝜏⇝𝑢, then 𝖼𝗅𝗈𝗌𝖾C(𝑒)=Λ¯𝑎.𝜆{¯𝑑𝑄:𝖣𝗂𝖼𝗍𝖳𝖾𝗅(𝑄)}.𝜁⋅𝑢. The empty residual is forced at the empty source environment; missing ground evidence or ambiguity makes closure reject. A bar over type or dictionary application denotes the corresponding repeated unary forms in canonical order.
For example, the complete evidence-directed elaboration of the opening term is as follows. Here Γ0 binds the source name 𝖾𝗊 to the target constant 𝖾𝗊♯ with its displayed qualified scheme. At both applications, 𝑆2, 𝑈, the normalizer template 𝜂, and every accumulated environment transport are identities. To keep the proof tree legible, its internal nodes suppress the unchanged indices C0;𝑑:𝖤𝗊𝐷(𝛼);Γ0 and their types; each node is an instance of the indexed judgment just defined. 𝖾𝗊⇝𝖾𝗊♯[𝛼]{𝑑}𝑥⇝𝑥𝖾𝗊𝑥⇝𝖾𝗊♯[𝛼]{𝑑}𝑥D−App𝑥⇝𝑥𝖾𝗊𝑥𝑥⇝𝖾𝗊♯[𝛼]{𝑑}𝑥𝑥D−AppC0;𝑑:𝖤𝗊𝐷(𝛼);Γ0⊢W𝐷𝜆𝑥.𝖾𝗊𝑥𝑥:𝛼→𝖡𝗈𝗈𝗅⇝𝜆𝑥:𝛼.𝖾𝗊♯[𝛼]{𝑑}𝑥𝑥D−Lam. Generalizing closes it as Λ𝛼.𝜆{𝑑:𝖤𝗊𝐷(𝛼)}.𝜆𝑥:𝛼.𝖾𝗊♯[𝛼]{𝑑}𝑥𝑥.
If the elaboration judgment above holds, then (𝑆⋆Γ)𝐷,Δ𝑃⊢𝑢:𝜏𝐷,erase((𝑆⋆Γ)𝐷),erase(Δ𝑃)⊢erase(𝑢):𝜏𝐷. where 𝑆 is the substitution returned by its index W. Closing a generalized source judgment produces the corresponding sequence of target type abstractions and dictionary arrows.
Proof. Induct on D-Var, D-Lam, D-App, and D-Let. Variable evidence has the required dictionary type by lemma 11.1; target type and dictionary applications therefore instantiate its translated scheme. More precisely, 𝜃†𝜅𝑥:Δ𝑄[𝜃]⇒𝖾Δ𝑄0[𝜃], where 𝑄0 is the predicate interface stored with 𝑥. Applying this transport to the selected ¯𝛿𝑞 gives the dictionary arguments expected by 𝑥[¯𝛼[𝜃]]. For abstraction the body induction hypothesis is under 𝑆⋆Γ,𝑥:𝑎, so its ordinary binder has type 𝑎[𝑆]𝐷. At application, 𝑆2†− and 𝑈†− transport both induction hypotheses by lemma 13.15 to 𝑈⋆𝑆2⋆𝑆1⋆Γ; the MGU gives the common domain. Applying 𝜂 to both normalized predicate sets gives the same dictionary telescope, so source and target applications use the same dictionary parameters. At let, the generalization split determines exactly the type and dictionary abstractions; 𝑆2†𝜁 transports the right-hand side, while residual dictionaries remain in Δ𝑃. Canonicalization evidence is well typed by lemma 11.2, so every reconstructed dictionary application typechecks. For erasure, the dictionary-abstraction case sends 𝜆{𝑑:𝐷}.𝑢 to 𝜆𝑑:𝐷.erase(𝑢) and uses the body induction hypothesis. The dictionary-application case sends 𝑢{𝛿} to erase(𝑢)erase(𝛿) and uses ordinary application. All remaining constructors use their homomorphic System F rule. ◻
Erase dictionary braces from 𝑈 to System F by erase(𝜆{𝑑:𝐷}.𝑢)=𝜆𝑑:𝐷.erase(𝑢),erase(𝑢{𝛿})=erase(𝑢)erase(𝛿). All other clauses are homomorphic. Instance constants and superclass projections retain their displayed signatures. Define surface evaluation by evidence insertion and top-level closure: 𝑒⇓C𝑤iff𝖼𝗅𝗈𝗌𝖾C(𝑒)=𝑢and𝑢⟶∗𝑤. Thus an implicit surface program executes through its unique evidence core; there is no second raw reduction relation that guesses dictionaries.
if erase(𝑢)⟶𝐸′, then some 𝑢′ satisfies 𝑢⟶𝑢′ and 𝐸′=erase(𝑢′).
Consequently a core reduction erases to a target reduction, and every target reduction from an erased core term lifts to at least one core reduction with the displayed erased endpoint.
Proof of Lemma 13.17 — Core–target step correspondence
Proof. Inspect the root rule. Ordinary beta, type beta, let beta, products, base operations, instance constructors, and superclass projections are homomorphic. Dictionary beta maps to ordinary target beta. Conversely, a target root and the typed outer constructor of the given 𝑢 select a corresponding core root; evaluation contexts lift structurally. The lift need not be unique because brace erasure is not injective: for example, an ordinary lambda and a dictionary lambda may erase to the same System F lambda. Induction on a step sequence gives forward simulation and existential reverse lifting for reflexive-transitive closure. ◻
Proof of Lemma 13.18 — Core dynamic preservation and value reflection
Proof. For clause 1, inspect the root contraction and close the result under the evaluation contexts. Ordinary beta, type beta, let beta, and dictionary beta use the corresponding substitution lemma. A primitive equation preserves the type because its two sides were checked at the same type in the same free-variable context; substituting its value arguments preserves that typing. For clause 2, inspect the two value grammars. Erasure changes a dictionary abstraction into an ordinary abstraction and otherwise preserves the outer constructor. Conversely, a core term whose erasure has a value outer constructor is an ordinary abstraction, type abstraction, dictionary abstraction, value pair, base value, or saturated dictionary constructor, so it is a core value. ◻
Proof of Theorem 11.7 — Forward operational simulation
Proof. Resolution, normalization, W, and the four elaboration rules are functional, so 𝑢 is unique up to renaming. Unfold the definition of 𝑒⇓C𝑤. Forward simulation gives the first clause. Repeated reverse lifting gives a core endpoint 𝑤 erasing to 𝑉. Value reflection in lemma 13.18 makes that endpoint a core value, giving the second clause. The endpoint is existential rather than fixed because erasure forgets the brace distinction. In particular, the displayed D-Let accounts for type/dictionary administrative redexes; the proof never identifies generalized surface let substitution with one homomorphic target step. ◻
For instance, erasing braces from the preceding core term gives the System F calculation (Λ𝛼.𝜆𝑑.𝜆𝑥.𝖾𝗊♯[𝛼]𝑑𝑥𝑥)[𝖨𝗇𝗍](𝜋1𝗈𝗋𝖽𝖨𝗇𝗍)0⟶∗(𝜋1𝗈𝗋𝖽𝖨𝗇𝗍)00⟶∗𝗍𝗋𝗎𝖾.
For the deterministic resolver of definition 13.1 and the W-indexed elaboration relation in this section, two successful elaborations of the same QTC0 W derivation produce alpha-equivalent evidence cores. Their System F erasures are therefore alpha-equivalent and contextually equivalent. This conclusion concerns the selected algorithm, not arbitrary declarative derivations or class laws.
Proof. Fresh type variables and dictionary binders may differ only by renaming. The HM MGU is unique up to such renaming; canonical predicate order is fixed; and lemma 11.1 proves that each request has at most one selected evidence term. An induction over D-Var, D-Lam, D-App, and D-Let therefore determines every core constructor and subterm. Homomorphic erasure preserves alpha-equivalence, and alpha-equivalent System F terms are contextually equivalent. ◻
Thus the result is determinism of the selected algorithm, not a coherence theorem for the declarative system.
The annotated ground compatibility slice
For the explicitly typed ground exercises in appendix A, use the distinct Church-Boolean dictionary notation 𝖤𝗊𝐷,𝐹(𝐴):=𝐴→𝐴→𝖡𝗈𝗈𝗅𝐹,𝑠::=⋯∣𝖾𝗊[𝐴](𝑠1,𝑠2)∣(𝐾𝐴⇒𝑠)∣𝑠⟨𝐾,𝐴⟩. These are annotations on QTC0 elaboration: bind, use, and discharge one displayed dictionary. They are not a second inference calculus. The symbols 𝖡𝗈𝗈𝗅𝐹,𝗍𝗋𝗎𝖾𝐹,𝖿𝖺𝗅𝗌𝖾𝐹 are the Church encoding from definition 5.15; they are recalled here because the following dictionary returns that encoding rather than the primitive 𝖡𝗈𝗈𝗅 used above. Let 𝖺𝗇𝖽𝐹:=𝜆𝑝.𝜆𝑞.𝑝[𝖡𝗈𝗈𝗅𝐹]𝑞𝖿𝖺𝗅𝗌𝖾𝐹,𝖾𝗊𝖡𝗈𝗈𝗅:=𝜆𝑝.𝜆𝑞.𝑝[𝖡𝗈𝗈𝗅𝐹]𝑞(𝑞[𝖡𝗈𝗈𝗅𝐹]𝖿𝖺𝗅𝗌𝖾𝐹𝗍𝗋𝗎𝖾𝐹),𝖺𝗅𝗅𝖲𝖺𝗆𝖾𝟥♯:=Λ𝐴.𝜆𝑑:𝖤𝗊𝐷,𝐹(𝐴).𝜆𝑥:𝐴.𝜆𝑦:𝐴.𝜆𝑧:𝐴.𝖺𝗇𝖽𝐹(𝑑𝑥𝑦)(𝑑𝑦𝑧).
Proof of Proposition 13.21 — Ground-table specialization
Proof. Type normalization fixes the lookup key. The local map contains at most one entry; if it contains none, the table contains at most one. Structural induction on the annotated term then forces the elaboration clause and all subterms. The proposition is also the premise-free closed-type specialization of theorem 11.8. ◻
★★☆ Derive the type of 𝖺𝗅𝗅𝖲𝖺𝗆𝖾𝟥♯ and reduce 𝖺𝗅𝗅𝖲𝖺𝗆𝖾𝟥♯[𝖡𝗈𝗈𝗅𝐹]𝖾𝗊𝖡𝗈𝗈𝗅𝗍𝗋𝗎𝖾𝐹𝗍𝗋𝗎𝖾𝐹𝖿𝖺𝗅𝗌𝖾𝐹. Then give an overlapping ground table and a duplicated local evidence key, and identify the failed hypothesis of proposition 13.21 in each case.
The principal calculus above resolves a predicate but never lets that resolution determine a type. Collections expose the missing dependency: 𝖼𝗅𝖺𝗌𝗌𝖢𝗈𝗅𝗅𝖾𝖼𝗍𝗌𝑐𝗐𝗁𝖾𝗋𝖾𝗍𝗒𝗉𝖾𝖤𝗅𝖾𝗆𝑐;𝖾𝗆𝗉𝗍𝗒:𝑐;𝗂𝗇𝗌𝖾𝗋𝗍:𝖤𝗅𝖾𝗆𝑐→𝑐→𝑐;𝗍𝗈𝖫𝗂𝗌𝗍:𝑐→𝖫𝗂𝗌𝗍(𝖤𝗅𝖾𝗆𝑐). The class predicate says that the operations exist. The associated synonym 𝖤𝗅𝖾𝗆𝑐 says which element type those operations share. It is a partial, saturated type-level function: the application is admitted only when 𝖢𝗈𝗅𝗅𝖾𝖼𝗍𝗌𝑐 is entailed.
This section is a bounded import, called ATS0. It does not strengthen the principality theorem for QTC0. Extend the predicate and instance environments by 𝜂::=𝑆¯𝜏(asaturatedassociatedsynonym),𝜋::=𝐾𝜏∣𝜂=𝜏,𝜃::=∀¯𝛼.𝑃⇒𝐾𝜏∣∀¯𝛼.𝜂=𝜏. Class declarations give an arity and kind to 𝑆. An instance gives both a class clause and an equality scheme. For example, 𝗂𝗇𝗌𝗍𝖺𝗇𝖼𝖾𝖤𝗊𝑎⇒𝖢𝗈𝗅𝗅𝖾𝖼𝗍𝗌(𝖫𝗂𝗌𝗍𝑎)𝗐𝗁𝖾𝗋𝖾𝗍𝗒𝗉𝖾𝖤𝗅𝖾𝗆(𝖫𝗂𝗌𝗍𝑎)=𝑎;⋯ contributes ∀𝑎.𝖤𝗊𝑎⇒𝖢𝗈𝗅𝗅𝖾𝖼𝗍𝗌(𝖫𝗂𝗌𝗍𝑎),∀𝑎.𝖤𝗅𝖾𝗆(𝖫𝗂𝗌𝗍𝑎)=𝑎. The equality scheme itself is unqualified, but its left side is well formed only where the associated class predicate is entailed. The instance checker verifies the right-hand side using the superclass environment and the instance premises, while the paired class clause supplies those premises whenever the reduction is applicable. This pairing prevents synonym reduction from exposing a type whose class precondition was never established.
Write Θ⊩𝜋 for entailment by class and equality schemes. In addition to specialization and modus ponens, equality has reflexivity, symmetry, transitivity, and congruence. The two distinctive typing rules are Θ⊩𝖢𝗈𝗅𝗅𝖾𝖼𝗍𝗌𝜏Θ⊢𝖤𝗅𝖾𝗆𝜏𝗍𝗒𝗉𝖾AT−WFΘ∣Γ⊢𝑒:𝜏1Θ⊩𝜏1=𝜏2Θ∣Γ⊢𝑒:𝜏2AT−Conv. Thus 𝖤𝗅𝖾𝗆𝑐 is not well formed merely because 𝑐 is a type. For instance, the annotation 𝖤𝗅𝖾𝗆𝑐→𝑐 must carry a premise 𝖢𝗈𝗅𝗅𝖾𝖼𝗍𝗌𝑐.
Evidence and type passing.
The source paper says that its typing rules admit the conventional type-directed evidence translation, but deliberately omits those extended rules [CKPJ05]. The following ground instance is therefore a local target sketch, not an imported elaboration theorem. Class predicates elaborate to ordinary dictionaries, the associated type is an explicit target type parameter, and equality solving chooses and normalizes that parameter at compile time. For the running class, use 𝖢𝗈𝗅𝗅𝖾𝖼𝗍𝗌𝐷(𝐶,𝐸):=𝐶×(𝐸→𝐶→𝐶)×(𝐶→𝖫𝗂𝗌𝗍𝐸). The method and list instance have target types 𝗂𝗇𝗌𝖾𝗋𝗍♯:∀𝐶.∀𝐸.𝖢𝗈𝗅𝗅𝖾𝖼𝗍𝗌𝐷(𝐶,𝐸)→𝐸→𝐶→𝐶,𝖼𝗈𝗅𝗅𝖾𝖼𝗍𝗌𝖫𝗂𝗌𝗍:∀𝐴.𝖤𝗊𝐷(𝐴)→𝖢𝗈𝗅𝗅𝖾𝖼𝗍𝗌𝐷(𝖫𝗂𝗌𝗍𝐴,𝐴). Consequently the ground source call at 𝖫𝗂𝗌𝗍𝖨𝗇𝗍 elaborates to 𝗂𝗇𝗌𝖾𝗋𝗍♯[𝖫𝗂𝗌𝗍𝖨𝗇𝗍][𝖨𝗇𝗍](𝖼𝗈𝗅𝗅𝖾𝖼𝗍𝗌𝖫𝗂𝗌𝗍[𝖨𝗇𝗍]𝖾𝗊𝖨𝗇𝗍). The equation 𝖤𝗅𝖾𝗆(𝖫𝗂𝗌𝗍𝖨𝗇𝗍)=𝖨𝗇𝗍 justifies the second type argument. It contributes no run-time proof object to this System-F-style target. An open pending equality remains in the source constraint set until later instantiation makes a rewrite possible.
The judgment Θ,𝑈∣𝑇Γ⊢𝖶𝑒:𝜏 returns class constraints Θ, pending equalities 𝑈, a substitution 𝑇, and a monotype 𝜏. Application unifies the operator’s inferred domain with the operand type after both substitutions. Repeated unification steps reduce saturated associated synonyms using the instance equations, decompose applications, perform ordinary first-order variable elimination, and leave irreducible equalities in 𝑈. For example, (𝖨𝗇𝗍,𝑎)=(𝖤𝗅𝖾𝗆𝑐,𝖡𝗈𝗈𝗅) returns [𝖡𝗈𝗈𝗅/𝑎] and the pending equation 𝖨𝗇𝗍=𝖤𝗅𝖾𝗆𝑐. If later 𝑐=𝖫𝗂𝗌𝗍𝖨𝗇𝗍, synonym reduction discharges it.
Well-formed programs require constructor-headed, specific, nonoverlapping instance heads; decreasing instance contexts; saturated associated applications; and a confluent, terminating synonym rewrite system. Programmer-written equality constraints have a variable in the designated class-index position. Define the fixed variables by 𝖥𝗂𝗑𝗏(𝑇)=∅,𝖥𝗂𝗑𝗏(𝑎)={𝑎},𝖥𝗂𝗑𝗏(𝜏1𝜏2)=𝖥𝗂𝗑𝗏(𝜏1)∪𝖥𝗂𝗑𝗏(𝜏2),𝖥𝗂𝗑𝗏(𝜂)=∅,𝖥𝗂𝗑𝗏((𝜂=𝜏)⇒𝜌)=𝖥𝗂𝗑𝗏(𝜏)∪𝖥𝗂𝗑𝗏(𝜌),𝖥𝗂𝗑𝗏((𝐾𝜏)⇒𝜌)=𝖥𝗂𝗑𝗏(𝜌),𝖥𝗂𝗑𝗏(∀𝑎.𝜎)=𝖥𝗂𝗑𝗏(𝜎)∖{𝑎}. Thus variables beneath an associated application do not count as fixed, whereas variables in the ordinary right-hand side of an equality constraint do. If ∀¯𝑎.𝑃⇒𝜏 is a method signature in class 𝐾𝛽, require 𝛽∉𝖥𝖵(𝑃)and𝛽∈𝖥𝗂𝗑𝗏(∀¯𝑎.𝑃⇒𝜏). Every annotation 𝑒::∀¯𝑎.𝜌 also requires ¯𝑎∩𝖥𝖵(𝜌)⊆𝖥𝗂𝗑𝗏(𝜌). These are the source’s admission conditions, not conclusions of inference.
Proof of Theorem 13.23 — Soundness of associated-type inference—imported
Proof. This is exactly Chakravarty, Keller, and Peyton Jones’s Theorem 2, under the well-formed-program hypotheses and judgment roles fixed above [CKPJ05]. Their proof factors through a syntax-directed declarative system; soundness of type reduction, one-step unification, its closure, and subsumption discharge the non-syntactic equality cases. Those lemmas are imported with the theorem, not reproved for QTC0. ◻
★★☆ Infer the substitution and pending equality produced by (𝖨𝗇𝗍,𝑎)=(𝖤𝗅𝖾𝗆𝑐,𝖡𝗈𝗈𝗅). Then instantiate 𝑐 first with 𝖫𝗂𝗌𝗍𝖨𝗇𝗍 and then with 𝖫𝗂𝗌𝗍𝖡𝗈𝗈𝗅. For each case, normalize the equality, decide whether inference can succeed, and write the target dictionary and type arguments for the corresponding use of 𝗂𝗇𝗌𝖾𝗋𝗍♯.
The imported source states completeness and principality only as beliefs [CKPJ05]. This chapter therefore imports neither. It also makes no claim for open type families, overlap, injectivity annotations, roles, dependent equality, or unrestricted modern GHC instance programs.
Source boundary.
The class examples and dictionary translation are from [WB89]; that paper’s larger principal-typing statement is explicitly conjectural [WB89]. The separation of qualified typing from evidence translation follows [HHPJW96], whose metatheorems are only outlined there and are not imported as proofs. Predicate entailment, context reduction, generalization, and ambiguity follow the executable specification in [Jon99]; that source is an implementation specification, not a mechanized metatheory. The finite superclass-closed effective table, full effective-head nonoverlap policy, normalization naturality, and factorization lemma are the book’s explicit bounded repair; they are not attributed to those larger systems. The proofs in this chapter are therefore for the explicitly restricted QTC0 above. They do not claim principality for Haskell’s full class system.
Stable and coherent implicits
COCHIS begins from a smaller failure than a large type-class program. Its contexts grow to the right, so the final implicit below is nearest: Δ=𝛽,?𝛽:𝑥,𝛼,?𝛼:𝑦. Before substituting 𝛽 for 𝛼, the query ?𝛽 skips ?𝛼 and returns 𝑥. After substitution, the nearer assumption has type ?𝛽 and the same query returns 𝑦. Equivalently, type application changes the evidence selected by 𝜆?𝛽.(Λ𝛼.𝜆?𝛼.?𝛽)𝛽 when compared with its type-beta reduct. Resolution that is merely deterministic is therefore not necessarily stable under substitution.
The comparison uses the paper’s exact predicative syntax. From here through the end of the comparison, 𝜎 ranges over COCHIS monotypes, not the qualified schemes of QTC0, and Δ is COCHIS’s full typing context, not the evidence-only context used above: 𝜌::=𝛼∣𝜌1→𝜌2∣∀𝛼.𝜌∣𝜌1⇒𝜌2,𝜎::=𝛼∣𝜎1→𝜎2,𝑒::=𝑥∣𝜆(𝑥:𝜌).𝑒∣𝑒1𝑒2∣Λ𝛼.𝑒∣𝑒𝜎∣?𝜌∣𝜆?𝜌.𝑒∣𝑒1𝗐𝗂𝗍𝗁𝑒2,Δ::=∅∣Δ,𝑥:𝜌∣Δ,𝛼∣Δ,?𝜌:𝑥. Only monotypes 𝜎 may instantiate ∀. Besides typing Δ⊢𝑒:𝜌, the deterministic specification has these judgment signatures: Δ⊢𝗋𝜌⇝𝐸,𝐴;Δ⊢𝖿[𝜌]⇝𝐸,𝐴;Δ;[Δ′]⊢𝗅𝜏⇝𝐸,Δ;[𝜌];𝑥⊢𝗆¯𝜌;¯𝑧;𝜏⇝𝐸,𝗌𝗍𝖺𝖻𝗅𝖾(𝐴;Δ;𝜌;𝑥;𝜏). These are, respectively, main resolution, focusing, nearest-first lookup, matching with returned goals and evidence placeholders, and permission to skip one candidate. The main rule sets 𝐴=𝗍𝗒𝗏𝖺𝗋𝗌(Δ); focusing strips ∀ and rule premises until a simple head remains; lookup scans Δ′ from right to left. It commits to the first match and may skip a candidate only when the displayed stability judgment holds. Concretely, 𝗌𝗍𝖺𝖻𝗅𝖾(𝐴;Δ;𝜌;𝑥;𝜏) means that no substitution valid for 𝐴;Δ makes the candidate 𝜌 match the query 𝜏; validity and matching are defined immediately after the rules.
Here is the load-bearing fragment of that resolution, including the recursive evidence plumbing. Write 𝐴;Δ⊢𝖿[¯𝜌]⇝¯𝐸 for the pointwise resolution of a sequence of goals. Matching a candidate returns both recursive goals ¯𝜌 and fresh placeholders ¯𝑧; the lookup rule resolves those goals in the full environment and substitutes the resulting evidence into the candidate evidence. The notation |𝜌| in this imported fragment is its own source-to-target type translation; it is unrelated to 𝖣𝗂𝖼𝗍𝖳𝖾𝗅, (−)𝐷, and erase(−) above.
𝗍𝗒𝗏𝖺𝗋𝗌(Δ);Δ⊢𝖿[𝜌]⇝𝐸
Δ⊢𝗋𝜌⇝𝐸
C-R-Main
𝐴;Δ,?𝜌1:𝑧⊢𝖿[𝜌2]⇝𝐸𝑧fresh
𝐴;Δ⊢𝖿[𝜌1⇒𝜌2]⇝𝜆𝑧:|𝜌1|.𝐸
C-R-IAbs
𝐴;Δ;[Δ]⊢𝗅𝜏⇝𝐸
𝐴;Δ⊢𝖿[𝜏]⇝𝐸
C-R-Simp
Δ;[𝜌];𝑥⊢𝗆¯𝜌;¯𝑧;𝜏⇝𝐸𝐴;Δ⊢𝖿[¯𝜌]⇝¯𝐸
𝐴;Δ;[Δ′,?𝜌:𝑥]⊢𝗅𝜏⇝𝐸[¯𝐸/¯𝑧]
C-L-Match
𝗌𝗍𝖺𝖻𝗅𝖾(𝐴;Δ;𝜌;𝑥;𝜏)𝐴;Δ;[Δ′]⊢𝗅𝜏⇝𝐸
𝐴;Δ;[Δ′,?𝜌:𝑥]⊢𝗅𝜏⇝𝐸
C-L-NoMatch
Δ;[𝜏];𝑥⊢𝗆∅;∅;𝜏⇝𝑥
C-M-Simp
Δ,?𝜌1:𝑧;[𝜌2];𝑥𝑧⊢𝗆¯𝜌;¯𝑧;𝜏⇝𝐸𝑧fresh
Δ;[𝜌1⇒𝜌2];𝑥⊢𝗆𝜌1,¯𝜌;𝑧,¯𝑧;𝜏⇝𝐸
C-M-IApp
Δ⊢𝜎Δ;[𝜌[𝜎/𝛼]];𝑥[𝜎]⊢𝗆¯𝜌;¯𝑧;𝜏⇝𝐸
Δ;[∀𝛼.𝜌];𝑥⊢𝗆¯𝜌;¯𝑧;𝜏⇝𝐸
C-M-TApp
The simplest lookup uses four of the rules immediately. For either 𝜃=𝗂𝖽 or 𝜃=[𝖨𝗇𝗍/𝛽], 𝑋Δ;[𝛽[𝜃]];𝑥⊢𝗆∅;∅;𝛽[𝜃]⇝𝑥C−M−Simp𝐴;Δ⊢𝖿[∅]⇝∅𝐴;Δ;[?𝛽[𝜃]:𝑥]⊢𝗅𝛽[𝜃]⇝𝑥C−L−Match𝐴;Δ⊢𝖿[𝛽[𝜃]]⇝𝑥C−R−SimpΔ⊢𝗋𝛽[𝜃]⇝𝑥C−R−Main. Thus the same lookup derivation selects 𝑥 before and after the ground substitution. The complete source typing and valid-substitution systems are Figs. 2 and 6 of [SdSOWM19]; its resolution, algorithm, unification, and termination systems are Figs. 7–10 on pp. 30–35.
Unambiguity is the inductive predicate 𝖴𝖠(𝐴;𝜌): 𝖴𝖠(𝐴;𝜏)iff𝐴⊆𝖿𝗍𝗏(𝜏),𝖴𝖠(𝐴;∀𝛼.𝜌)iff𝖴𝖠(𝐴∪{𝛼};𝜌),𝖴𝖠(𝐴;𝜌1⇒𝜌2)iff𝖴𝖠(𝐴;𝜌1)and𝖴𝖠(𝐴;𝜌2). Write 𝗎𝗇𝖺𝗆𝖻(𝜌) for 𝖴𝖠(∅;𝜌); implicit binders and queries require it.
The valid-substitution judgment is 𝗏𝖺𝗅𝗂𝖽(𝐴;Δ;𝜃). The empty substitution is valid. Its only extension clause admits [𝜎/𝛼]⋅𝜃 when 𝛼∈𝐴, the environment splits as Δ0,𝛼,Δ1, the monotype 𝜎 is well scoped in the prefix Δ0, and 𝗏𝖺𝗅𝗂𝖽(𝐴∖{𝛼};[𝜎/𝛼](Δ0,Δ1);𝜃). Finally, 𝗌𝗍𝖺𝖻𝗅𝖾(𝐴;Δ;𝜌;𝑥;𝜏) says that there is no such valid 𝜃 under which the skipped 𝜃𝜌 matches the query 𝜃𝜏. This is the exact side condition that rejects the witness above; ordinary deterministic lookup alone would accept it.
Recursive rules are admitted only when each premise head is structurally smaller than the result head and every type variable occurs no more often in the premise than in the result. This is the comparison’s one selected mechanism: stable implicit resolution, not a second extension of QTC0.
Imported proof.Source. Items 1–6 import Theorems 5.1–5.6 and Lemmas 5.1–5.3 of [SdSOWM19] for exactly the calculus and side conditions frozen above. The paper’s mutual inductions provide the weakening, substitution, resolution, and translation lemmas; its structural measure proves termination of recursive resolution. System F strong normalization and the operational simulation give item 6. No COCHIS principality theorem, result for arbitrary lexical implicits, or result for QTC0 is imported. ◻
The contrast is now precise. QTC0 obtains coherence by an admissible superclass-closed instance environment with fixed candidate priority, canonical constraints, and functional evidence construction. COCHIS admits lexical implicit evidence, so it needs unambiguity and valid substitutions to make resolution stable as types change.
★☆☆ Write both evidence terms selected by the instability witness. Then remove the nearer ?𝛼 assumption and explain why lookup no longer skips a candidate, so the stability side condition is not invoked at all.
★★☆ Trace the preceding counterexample twice: first without the derived clause and then with it. Next start from {𝖮𝗋𝖽𝛾,𝖤𝗊𝛽} and apply 𝑆=[𝖫𝗂𝗌𝗍𝛼/𝛾] followed by 𝑇=[𝖫𝗂𝗌𝗍𝛼/𝛽]. Verify that without closure the sequential action rejects although the direct (𝑆;𝑇) action succeeds, whereas the two actions compose in the superclass-closed table.
★★★ Suppose a let right-hand side makes W return 𝑃1={𝖤𝗊𝛼,𝖲𝗁𝗈𝗐𝛽} and 𝜏1=𝛽→𝖡𝗈𝗈𝗅, while ftv(Γ)={𝛼}. Compute the generalized and residual predicate sets and the resulting scheme. Then explain which environment equation lets the body factorization reuse that scheme, and exhibit the failure if 𝖤𝗊𝛼 is generalized instead of retained.
★★☆ Choose one restriction excluded from QTC0. Use an overlapping effective head, a variable-headed instance, or an ambiguous generalized scheme. Give the smallest program that violates the corresponding proof step; do not propose an informal repair without a replacement invariant.
Complete the practical project qualified-resolver. The executable must validate nonoverlap after superclass closure and proper-subterm instance descent; resolve exact local evidence before a superclass projection and before global instances, fall back from a missing direct instance to the selected superclass-derived instance, and print an explicit evidence tree.
Its first oracle line is PASS standard accepted. The next three are 𝙴𝚚𝙻𝚒𝚜𝚝(𝙴𝚚𝙵𝚛𝚘𝚖𝙾𝚛𝚍(𝙾𝚛𝚍𝙸𝚗𝚝)),𝙴𝚚𝙵𝚛𝚘𝚖𝙾𝚛𝚍(𝚍𝙾𝚛𝚍),𝙴𝚚𝙵𝚛𝚘𝚖𝙾𝚛𝚍(𝙾𝚛𝚍𝙻𝚒𝚜𝚝(𝙾𝚛𝚍𝙸𝚗𝚝)). The final three case lines carry the corresponding PASS prefix before ambiguous, cycle, and missing; the declared summary line follows.
Run kappa check, kappa test, kappa run, and kappa audit; then demonstrate four typechecking semantic mutations: reversing declaration validation, disabling the descent check, erasing local evidence, and disabling superclass-derived instance fallback. The companion directory is