Lectures onType Theory
Chapter 15
Chapter 15Optional

MixML, Recursive Linking, and Definedness

Prerequisites. Direct starred prerequisites: Chapter 12. No later core chapter depends on this route.

A component needed before it can be defined

Consider two modules. A lexer exports tokens but imports a table of keywords; a parser exports that table but imports tokens. importsexportsLexerkeywords:Tabletoken:CharTokenParsertoken:CharTokenkeywords:Table An ordinary functor can break this cycle only by choosing one direction first. Recursive linking must instead connect both pairs of components and must still prevent the lexer from reading keywords while its slot is empty.

Definition 15.1 — The finite linking calculus Mix_0

Let p range over finite component paths and let A range over the pure core types of chapter 12. A polar component is p:A, an import, or p+:A, an export. A signature Σ is a finite map from paths to polar components. Modules are generated by M,N::=imp(p:A)def(p=e:A){=M}MwithNsealΣ(M)complete(M). Paths in a nested structure are prefixed by its label. A core expression records finite sets rd(e) and wr(e) of slots read and written during initialization. The fragment requires wr(e)={p} in def(p=e:A).

The polarity belongs to a component occurrence, not to its core type. Thus p:A and p+:A may be linked, while two exports at the same path are competing definitions.

Definition 15.2 — Compatible signatures

For signatures Σ1,Σ2, write merge(Σ1,Σ2)=Σ when, at every path p:

  1. a component occurring on one side only is copied to Σ;

  2. equal-typed components of opposite polarity become the export p+:A;

  3. two imports of the same type remain the import p:A; and

  4. two exports, or two components with different types, make the merge undefined.

The path sets are finite, so merge is a partial algorithm.

For the running family, prefixing gives ΣL={keywords:Table,token+:CharToken},ΣP={token:CharToken,keywords+:Table}. Both opposite-polarity pairs disappear as imports, hence merge(ΣL,ΣP)={keywords+:Table,token+:CharToken}.

Exercise 15.1 — Merge is functional and commutative

★☆☆ Prove that if merge(Σ1,Σ2)=Σ and merge(Σ1,Σ2)=Σ, then Σ=Σ. Prove also that defined merge is commutative. Explain why left bias between two equal-typed exports cannot be observed in this signature: signature entries carry a polarity and a type, not an implementation value. Finally replace the rejection of unequal overlapping components by left bias and give a one-path counterexample to commutativity.

Compatibility solves the static wiring problem but not initialization. If token is evaluated before keywords, its initializer may read an empty slot even though the final signature is complete.

Definedness is a state transition

Definition 15.3 — Initialization judgment

Let Ω be a finite map from slots to core types, and let D be a finite subset of dom(Ω). Write Ω;Dcoree:A when ordinary core typing gives e:A and rd(e)D. The judgment Ω;DM:ΣD means that M has signature Σ, reads only slots in D, writes each absent slot at most once, and leaves exactly the slots D defined. Its primitive rules for imports, definitions, and sequencing are

Ω(p)=A
Ω;Dimp(p:A):{p:A}D
Mix-Imp
Ω(p)=AΩ;Dcoree:ApDwr(e)={p}
Ω;Ddef(p=e:A):{p+:A}D{p}
Mix-Def
Ω;DM:Σ1D1Ω;D1N:Σ2D2merge(Σ1,Σ2)=Σ
Ω;DMwithN:ΣD2
Mix-With

For a label , let () prefix every path in a map or set. Let 1Ω and 1D select the entries below and remove that prefix. Thus 1D={q.qD}. For a finite visible path set Q, let Σ|Q restrict a signature. The remaining rules are

1Ω;1DM:ΣD0
Ω;D{=M}:Σ(D(1D))D0
Mix-Struct
Ω;DM:ΣDQdom(Σ)Σ|Q=Σ0
Ω;DsealΣ0(M):Σ0D
Mix-Seal
Ω;DM:ΣDpdom(Σ).A.Σ(p)=p+:A
Ω;Dcomplete(M):ΣD
Mix-Complete

Sealing hides paths only after checking the body; it does not erase their initialized cells from D.

The slice formulation lets sibling structures share one ambient state without requiring that state to carry two different outer prefixes. For example, let ΩLP contain Lexer.token:CharToken and Parser.keywords:Table, and choose initializers with empty read sets. Put L0={Lexer=def(token=t0:CharToken)},P0={Parser=def(keywords=k0:Table)}. Their signatures are ΣL0={Lexer.token+:CharToken} and ΣP0={Parser.keywords+:Table}. Two uses of Mix-Struct, followed by Mix-With, give ΩLP;L0:ΣL0{Lexer.token},ΩLP;{Lexer.token}P0:ΣP0{Lexer.token,Parser.keywords}. Their signatures have disjoint paths, so their sequential composition merges.

The order of Mix-With matters operationally. Define the keyword table without reading token, then define the token function while reading keywords: write K=def(keywords=k:Table) and T=def(token=t:CharToken). Then

Ω;K:Σk{keywords}Ω;{keywords}T:Σt{keywords,token}merge(Σk,Σt)=Σ
Ω;KwithT:Σ{keywords,token}
Mix-With

The reverse order has no derivation when keywordsrd(t), because the subset premise of Mix-Def fails.

Lemma 15.4 — Definedness grows exactly by writes

If Ω;DM:ΣD, then DD, and every path in DD is written exactly once by M.

Proof of Lemma 15.4 — Definedness grows exactly by writes

Proof. Proceed by rule induction. Mix-Imp adds no path. In Mix-Def, the side condition pD gives DD{p}, and the singleton write set gives the exact new write. In Mix-With, the induction hypotheses give DD1D2. A path in D2D lies either in D1D or in D2D1. The two sets are disjoint, and the corresponding induction hypothesis gives its unique write. In the structure case, entries outside the -slice are unchanged, while prefixing injectively transports the premise’s new writes inside the slice. The two regions are disjoint, so both claims follow. Sealing does not change execution, and completeness adds no write. ◻

Lemma 15.5 — No read before definition

If Ω;DM:ΣD, then every read performed while initializing M names a slot defined earlier in the same sequential trace or a slot in D.

Proof of Lemma 15.5 — No read before definition

Proof. Rule induction fixes the temporal order. Imports perform no read. For a definition, the core judgment’s read condition is exactly the claim. For Mix-With, apply the first induction hypothesis from D to D1, then the second from D1 to D2. The remaining rules preserve the trace and merely change path prefixes or visibility. ◻

Exercise 15.2 — The missing side condition

★☆☆ Delete pD from Mix-Def. Construct a derivable module that seals its first definition to the empty visible signature and then assigns the same slot again. Explain why the seal makes signature merge defined, and identify the exact clause of lemma 15.4 that becomes false.

An ordered slot trace

The finite module judgment rejects an early read by threading the set D. The following command calculus isolates that stronger, ordered-initialization property. It is a teaching calculus, not the full LTG typing judgment.

Definition 15.6 — Ordered slot commands and extracted traces

Write L,U for the empty-cell and filled-cell modes. A mode environment Ξ is a finite map of bindings x:AL or x:AU. Values are pure: the auxiliary judgment ΞUvv:A may inspect only the unrestricted projection ΞU of Ξ. Commands and scoped event traces are c::=return vget xset x vc1;c2newA(x.c),t::=ϵget xset xt1t2νx.t. The judgment Ξc:BΞt both checks a command and extracts its trace:

ΞUvv:A
Ξreturn v:AΞϵ
Slot-Return
Ξ=Ξ0,x:AU
Ξget x:AΞget x
Slot-Get
Ξ=Ξ0,x:ALΞ0Uvv:A
Ξset x v:1Ξ0,x:AUset x
Slot-Set
Ξc1:1Ξ1t1Ξ1c2:BΞ2t2
Ξc1;c2:BΞ2t1t2
Slot-Seq
xdom(Ξ)dom(Ξ)Ξ,x:ALc:BΞ,x:AUt
ΞnewA(x.c):BΞνx.t
Slot-New

Thus allocation creates one local L-mode obligation, setting changes that mode to U, and leaving the scope requires the obligation to have been discharged.

Definition 15.7 — Trace validation

The judgment ΞtrtΞ is generated by

ΞtrϵΞ
Tr-Empty
Ξ=Ξ0,x:AU
Ξtrget xΞ
Tr-Get
Ξ=Ξ0,x:AL
Ξtrset xΞ0,x:AU
Tr-Set
Ξtrt1Ξ1Ξ1trt2Ξ2
Ξtrt1t2Ξ2
Tr-Seq
xdom(Ξ)dom(Ξ)Ξ,x:ALtrtΞ,x:AU
Ξtrνx.tΞ
Tr-New

A trace is safe precisely when this partial validation judgment is derivable.

Proposition 15.8 — Ordered slot-trace safety

If Ξc:BΞt, then ΞtrtΞ. Consequently each get x in t occurs while x has mode U, and between an allocation νx and the end of its scope there is exactly one set x.

Proof of Proposition 15.8 — Ordered slot-trace safety

Proof. Induct on the command derivation. Return, get, and set select the corresponding trace rule. Composition applies the two induction hypotheses in sequence. For allocation, the induction hypothesis validates the body from x:AL to x:AU, so Tr-New closes the scoped trace.

For the consequence, inspect a validation derivation. Only Tr-Get emits a get, and its premise requires mode U. Only Tr-Set changes the local mode; it requires L and produces U, so it cannot occur twice. Rule Tr-New requires that one such change has occurred before the scope closes. ◻

The full LTG boundary includes black holes

The source target uses linearity for single assignment and eventual definition, but deliberately does not enforce the temporal read discipline of definition 15.6.

Definition 15.9 — The load-bearing LTG store interface

In LTG, modes are ι::=LU. Among its types and terms are reference types (?τ)ι, allocation new τ, definition def e1:=e2, and dereference !e. The full calculus also has moded kinds, functions, records, universal and existential types, fresh type names, and type-name definition. The run-time categories relevant here are σ::=ϵσ,α:?κσ,α:=τ:κ,s::=ϵs,x:?τs,x:=e:τ,ξ::=σ;s;e. The value-store reductions include σ;s;E[new τ]0σ;s,x:?τ;E[x],σ;s1,x:?τ,s2;E[def x:=e]0σ;s1,x:=e:τ,s2;E[{}],σ;s1,x:=e:τ,s2;E[!x]0σ;s1,x:=e:τ,s2;E[e],σ;s1,x:?τ,s2;E[!x]0. Store typing assigns (?τ)L to x:?τ and (?τ)U to x:=e:τ. Definition consumes an L-mode capability, while dereference requires a U-mode occurrence. Crucially, LTG splitting contains (?τ)L(?τ)U=(?τ)L. Hence an unrestricted read capability may coexist with the linear obligation to fill the cell. LTG permits an early dereference, which reduces to ; its type safety theorem does not remove that outcome.

The ordered trace checker can be used before LTG elaboration: map an empty slot to mode L, a filled slot to mode U, and accept only traces validated by definition 15.7. Equation (15.1) is intentionally absent from that checker. Thus proposition 15.8 proves a local initialization-order property, while the published LTG result proves a different single-assignment-and-progress property.

Three passes and the exact imported boundary

The full MixML rules are declarative: linking chooses locators and fresh type names. A checker must remove that nondeterminism without changing which modules are typable. The source construction separates three questions.

Definition 15.10 — Full MixML semantic-signature shell

The paper leaves the core constructor grammar parametric. Let A range over the selected core’s beta-normal, eta-long semantic constructors, equipped with the paper’s decidable kinding, elaboration, subtyping, and substitution judgments. Relative to that explicit parameter, the complete MixML semantic objects used by the imported rules are Σ::=[[=A]][[A]]±[[Φ]]±{|:Σ|},Φ::=α¯.β¯.(Li;Le;Σ),L::=[[=α]]{|:L|},R::=[[=A]]{|:R|},Γ::=ϵΓ,X:|Σ|. Here [[A]] and [[A]]+ are term imports and exports; unit components have the same polarities. Type imports and abstract type exports are represented by the two locators in Φ. Absolute signature |Σ| changes polar imports to exports before storing a module in Γ. Realizer disjoint union is written R1R2, and R#Σ means disjoint path domains.

Template erasure retains kinds and shapes: S::=[[κ]][[F]]±{|:S|},F::=LT;κ¯;S. It erases atomic term components, replaces type definitions by their kinds, and commutes with path domains, absolute signatures, locator restriction, and disjoint union. These are the full semantic categories of the imported judgments; they are not the polar path maps of Mix0.

Definition 15.11 — Three-pass interface

For the full source syntax of Rossberg and Dreyer, the three passes are

  1. ΓTMLT;κ¯;S computes component domains, locator shapes, polar unit shapes, and export kinds while erasing atomic term components;

  2. Γ;R;β¯statM:Σs computes static type components with the template-fixed locator and export-kind choices; and

  3. Γ;R;β¯mainM:Σe checks core terms and produces LTG evidence e.

Here is evidence elaboration, not evaluation. All three judgments use the paper’s full semantic signatures, locator disjointness conditions, freshness conditions, and analysis/synthesis well-formedness classes.

The deterministic link rule makes the interaction of the passes inspectable. For (X=M1) with M2, template computation first produces ΓTM1RTR1TL1T;κ¯β1;S1,ΓT,X:|S1|M2RTR2TL2T;κ¯β2;S2, with (R1L1)#(R2L2). These domains determine the common external imports R, the unmatched imports R1,R2, and the cross-linked locators L1,L2; no pass guesses that partition again. The static premise checks Γ,X:|Σ1|;RR2L2;β¯2statM2:Σ20 and bidirectional lookup computes the unique normalizing substitution (L1;Σ1)(L2;Σ20)δ. The main premises then check M1 at Σ1, recheck M2 under δΓ,X:|δΣ1| and δL2 at Σ2, and finish with the deterministic merge δΣ1+Σ2Σ. Equations (15.2)(15.5) are the mechanism of the paper’s Link-Det rule: templates fix domains and fresh-kind arities, the static pass exposes type equations, lookup computes δ, and the main pass checks values with those equations available.

On the lexer–parser family, the template contains two paths with opposite polarities. The static pass checks that both occurrences of keywords have type Table and both occurrences of token have type CharToken. The main pass then emits two cells, wires each import to the corresponding export, and sequences the initializers in an order accepted by the LTG modes.

Theorem 15.12 — Full MixML/LTG theorem boundary; exact import

For the MixML and LTG signatures of Rossberg–Dreyer, including their well-formed analysis and synthesis signatures and the assumed sound and complete algorithms for the chosen pure core language, the following results hold.

  1. Evidence translation is complete and sound: the paper’s Theorems 8.1 and 8.7 relate declarative MixML derivations to well-typed LTG terms.

  2. Template computation is complete (Theorem 9.8), and the three-pass algorithm is complete and sound (Theorems 9.9 and 9.10).

  3. MixML type checking is decidable and inferred signatures are unique (Corollary 9.11 and Theorem 9.12).

  4. LTG preservation and progress are Theorems 7.10 and 7.14. A well-typed non-error configuration either steps or is a value configuration whose term and type cells are all defined. Dereferencing an undefined cell may step to , as displayed in definition 15.9.

Proof of Theorem 15.12 — Full MixML/LTG theorem boundary; exact import

Proof. This theorem imports the named results from [RD13]. The bridge is literal: definition 15.10 reproduces the complete MixML semantic and template shells of Figures 4, 8, and 25 relative to their stated core parameter; (15.2)(15.5) reproduce the premises that replace declarative linking in Link-Det of Figure 29; and definition 15.9 reproduces the reference-store fragment of Figures 13–15. Consequently a derivation of the displayed three-pass judgments is a derivation in the hypotheses of Theorems 9.8–9.10, and its evidence conclusion is the input of Theorems 8.1 and 8.7.

The theorem is not obtained from Mix0 or from the ordered trace checker. The source proofs use environment-splitting substitution for LTG, analysis/synthesis well-formedness for elaboration, deterministic signature approximation for the static pass, and deterministic shapes for template completeness. These hypotheses are retained because removing any one changes the source judgment or invalidates its induction. ◻

Remark 15.13 — No transfer to Standard ML

The theorem concerns the frozen MixML/LTG pair. Standard ML lacks MixML’s polar semantic signatures and is not translated by the stated evidence judgments. Dreyer’s recursive-module calculus and Leroy’s modular module system give useful predecessor comparisons, but their soundness results do not instantiate theorem 15.12.

Exercise 15.3 — Classify the claims

★★☆ For each claim, state whether theorem 15.12 establishes it and name the decisive hypothesis: (i) a successful full MixML elaboration is LTG-typed; (ii) every Standard ML recursive module is safe; (iii) a non-error terminal LTG module has no empty component; (iv) arbitrary impure core-language extensions preserve completeness. State separately what can happen after an early dereference.

Suggested first pass.

None of these problems is a prerequisite for a later chapter. Begin with exercise 15.4, then implement exercise 15.6.

Exercise 15.5 — Two notions of completeness

★★☆ Construct a module whose merged signature has only exports but whose chosen initializer order fails. State separately signature completeness and LTG definedness, and prove that neither definition implies the other without an elaboration-soundness premise.

Exercise 15.6 — Definedness checker

★★★ Practical project.mixml-checker Implement in Kappa a finite Mix0 merge and initialization checker. Maintain the invariant that the state set contains exactly the slots written by the accepted prefix. The program must accept the ordered keyword/token family, reject its early-read reversal, reject duplicate exports, reject a type mismatch, and reject a cyclic pair in both orders. The exact five-case output recorded in appendix E is the acceptance test; an empty Kappa audit is also required.

Exercise 15.7 — A disciplined extension

★★★ Define a parallel composition rule for two modules whose read/write sets are independent. State the independence condition, prove that either sequential order is derivable under that condition, and show by counterexample why disjoint write sets alone do not suffice.

Search the book

Type to search the local edition.