Suppose one function returns its argument unchanged. The same function satisfies both typings 𝖭𝖺𝗍→𝖭𝖺𝗍and𝖡𝗈𝗈𝗅→𝖡𝗈𝗈𝗅. An intersection type records several typings of one value. A single arrow with domain 𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅 is also too weak if it forgets which result corresponds to which input. The useful type is therefore (𝖭𝖺𝗍→𝖭𝖺𝗍)∧(𝖡𝗈𝗈𝗅→𝖡𝗈𝗈𝗅). The same obstruction appears after control flow. If one branch returns a natural and another a Boolean, neither branch type is above the other. Their least set-theoretic join is the union type𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅, whose values may come from either branch.
Chapter 8 ordered the types built from the ordinary constructors, using a declarative relation <:; joins and meets were properties of that order, not syntax. Here we change the language: ∨,∧,¬ are type constructors. Its semantic order is literal inclusion of type interpretations. The two orders obey familiar laws, but no unstated identification between them is used.
The notation suggests sets, but that suggestion is not yet a definition. For products, unions, and complements, ordinary sets suffice. For arrows, “the set of all functions between two sets” creates two problems. Write 𝐷 for the set of values we are trying to build. A function value would then be a set of input-output pairs drawn from 𝐷 itself, so the defining equation contains 𝐷 on both sides; Cantor’s theorem also forbids the resulting full-powerset equation. The required domain must therefore admit finite observable graphs without containing its full powerset, and its definition must be stratified so that every graph mentions only values from smaller ranks.
One value, two specifications
Fix three nonempty, pairwise disjoint sets of constants, with basic types 𝖭𝖺𝗍, 𝖡𝗈𝗈𝗅, and 𝖴𝗇𝗂𝗍. We use constants 𝗓𝖾𝗋𝗈,𝗌𝗎𝖼𝖼(𝗓𝖾𝗋𝗈),…, 𝗍𝗋𝗎𝖾,𝖿𝖺𝗅𝗌𝖾, and 𝗎𝗇𝗂𝗍.
Types are finite trees generated by 𝐴,𝐵::=0∣𝑏∣𝐴×𝐵∣𝐴→𝐵∣𝐴∨𝐵∣¬𝐴. Define 1:=¬0, 𝐴∧𝐵:=¬(¬𝐴∨¬𝐵), and 𝐴∖𝐵:=𝐴∧¬𝐵. An atom is a basic type, a product type, or an arrow type. Boolean connectives may occur inside the two components of product and arrow atoms. There are no infinite or recursive type trees.
Call the finite annotated calculus developed in this chapter 𝜆𝖥𝖦, for “finite graphs.”
This spelling keeps term constants distinct from the empty type 0 and universal type 1:=¬0.
An overloaded abstraction carries a nonempty interface: 𝜆(𝐴1→𝐵1;…;𝐴𝑛→𝐵𝑛)𝑥.𝑒. The annotation says that the same body must meet every arrow specification. The immediate obligation is to state when all of these arrow specifications may be assigned to one abstraction.
Write 𝐼=(𝐴1→𝐵1;…;𝐴𝑛→𝐵𝑛) for a nonempty written interface. A well-shaped interface has 𝑛=1, or, when overloaded, has only test types—the Boolean shape tests generated by the grammar below—as its domains. Here 0 and 1 are the empty and universal types, written 𝖡𝗈𝗍 and 𝖳𝗈𝗉 in chapter 8. A test type is generated by 𝑈,𝑉::=0∣1∣𝑏∣𝖥𝗎𝗇∣𝑈×𝑉∣𝑈∨𝑉∣𝑈∧𝑉∣¬𝑈, where the only arrow form is the universal function test 𝖥𝗎𝗇=0→1. The terms in this fragment are generated by 𝑒::=𝑥∣𝜆𝐼𝑥.𝑒; the abstraction binds 𝑥 in 𝑒. The interface well-shapedness condition belongs to abstraction introduction. The intersection-introduction fragment has three rules:
𝑥:𝐴∈Γ
Γ⊢𝑥:𝐴
T-Var
Γ,𝑥:𝐴𝑖⊢𝑒:𝐵𝑖(1≤𝑖≤𝑛)
Γ⊢𝜆𝐼𝑥.𝑒:𝑛⋀𝑖=1(𝐴𝑖→𝐵𝑖)
T-Abs
Γ⊢𝑒:𝐴Γ⊢𝑒:𝐵
Γ⊢𝑒:𝐴∧𝐵
T-Inter
Rule T-Abs carries the interface side condition. These rules contain no subtyping premise. They state only that one annotated body checks at every written arrow and that the resulting term may retain more than one independently derived type.
Take 𝑒=𝑥. The complete abstraction derivation is 𝑥:𝖭𝖺𝗍∈𝑥:𝖭𝖺𝗍𝑥:𝖭𝖺𝗍⊢𝑥:𝖭𝖺𝗍T−Var𝑥:𝖡𝗈𝗈𝗅∈𝑥:𝖡𝗈𝗈𝗅𝑥:𝖡𝗈𝗈𝗅⊢𝑥:𝖡𝗈𝗈𝗅T−Var⋅⊢𝜆(𝖭𝖺𝗍→𝖭𝖺𝗍;𝖡𝗈𝗈𝗅→𝖡𝗈𝗈𝗅)𝑥.𝑥:(𝖭𝖺𝗍→𝖭𝖺𝗍)∧(𝖡𝗈𝗈𝗅→𝖡𝗈𝗈𝗅)T−Abs. Define the one-body overloaded identity in this derivation as 𝗌𝖺𝗆𝖾; it has type (9.1) without relying on an undeclared primitive operation.
An intersection is not a product. A value of 𝐴×𝐵 is a pair, and projection selects a component. A value of 𝐴∧𝐵 is one value accepted at both types. There is no intersection constructor and no projection from an intersection. Rule T-Inter reuses both the expression and its context.
Intersection also has a resource-sensitive, non-idempotent meaning: repeated copies of a type record repeated uses rather than collapsing by 𝐴∩𝐴=𝐴. One representative comparison rule is Γ⊢𝑒:𝐴Δ⊢𝑒:𝐵Γ⊎Δ⊢𝑒:𝐴∩𝐵. Here ⊎ is multiset sum: multiplicities from both premises are added. We write ∩ only inside this comparison so that its resource-sensitive connective remains visibly distinct from the idempotent ∧ and from meta-level set intersection. The two contexts are multisets and therefore record two uses. Such systems can measure normalization, but those results do not transfer to the idempotent rule above, whose premises deliberately share Γ. We use intersection only as a set-theoretic specification connective here.
The finite model interprets the type grammar of definition 9.4: ∧,∨, and ¬ become Boolean operations on sets, while arrows become finite graphs.
For any candidate carrier 𝐷, put 𝐷Ω=𝐷∪{Ω}, where Ω∉𝐷. Trying to solve 𝐷=𝐶+𝐷2+P(𝐷×𝐷Ω) is impossible: the full powerset is strictly larger than 𝐷. Finite graphs remove that obstruction.
Omitting Ω creates a different failure. If graphs contained only edges in 𝐷×𝐷, then the empty graph would vacuously satisfy every arrow atom and there would be no finite witness that a graph is undefined on one chosen input. In particular the counterexample edge {(𝑑,Ω)} needed to refute an arrow membership could not be formed. The extra output marker records precisely this finite failure observation.
Let 𝐶 be the disjoint union of the basic constants. The domain 𝐷 is the universal finite-graph domain: the set of finite terms 𝑑::=𝑐∣(𝑑1,𝑑2)∣{(𝑑1,𝛿1),…,(𝑑𝑛,𝛿𝑛)},𝛿::=𝑑∣Ω, including the empty graph. Equivalently, it is the initial solution of 𝐷=𝐶+𝐷2+P𝑓(𝐷×𝐷Ω). The three summands are disjoint and are called the basic, product, and function shapes. This use of shape classification is unrelated to the kinds that classify type operators in chapter 9.
Equivalently, rank a constant and the empty graph by zero, rank a pair one above the maximum rank of its components, and rank a nonempty graph one above the maximum rank of every input and non-Ω output occurring in it. If 𝐷𝑛 is the set of terms of rank at most 𝑛, then 𝐷=⋃𝑛∈ℕ𝐷𝑛. This cumulative presentation is the well-founded construction meant by “initial solution”; no cardinal fixed-point assumption is hidden in the notation.
The symbol Ω records that a graph may fail on an input. It is not a denotation of the empty type and belongs to no subset of 𝐷.
Fix once and for all a finite family of basic type names 𝑏, nonempty pairwise disjoint tag sets 𝐵𝑏, and 𝐶=⋃𝑏𝐵𝑏. Every semantic judgment in this chapter is relative to this standing assignment. Define [[𝐴]]⊆𝐷 by structural recursion on the finite type tree 𝐴: [[0]]=∅,[[𝑏]]=𝐵𝑏,[[𝐴∨𝐵]]=[[𝐴]]∪[[𝐵]],[[¬𝐴]]=𝐷∖[[𝐴]],[[𝐴×𝐵]]=[[𝐴]]×[[𝐵]],[[𝐴→𝐵]]={𝑅∈P𝑓(𝐷×𝐷Ω)∣(𝑑,𝛿)∈𝑅∧𝑑∈[[𝐴]]⇒𝛿∈[[𝐵]]}.Semantic subtyping is inclusion of interpretations, and semantic equivalence is mutual inclusion: 𝐴≤𝐵⟺[[𝐴]]⊆[[𝐵]],𝐴=D𝐵⟺𝐴≤𝐵∧𝐵≤𝐴.1
The interpretation [[−]] is defined only for types. Term typing and reduction remain syntactic, and the typecase test inspects the exact finite shape of a value. No adequacy theorem relating abstractions to graph elements is assumed.
Consequently, this chapter does not identify 𝐴≤𝐵 with the coarser claim that every closed value typable at 𝐴 is typable at 𝐵. The graph order deliberately contains failure edges (𝑑,Ω) used by arrow inversion and callability; a value-only order would erase those witnesses and would require a different completeness argument. No agreement between the two orders is needed for the syntactic safety theorem.
No recursion on 𝑑 is needed for these finite types: every denotation clause mentions only strict type subtrees. The rank recursion constructs the nested graph elements of the ambient domain 𝐷, while type denotation is structural recursion on finite types. The definition also shows why 1→1 is not the type of every graph: an edge (𝑑,Ω) violates it. Every graph does inhabit 0→1, since there is no input in [[0]] on which it can fail.
The types modulo =D form a Boolean algebra. Products are covariant in both arguments. Arrows are contravariant in their domain and covariant in their codomain: 𝐴′≤𝐴𝐵≤𝐵′⟹(𝐴→𝐵)≤(𝐴′→𝐵′). Moreover, ((𝐴→𝐶)∧(𝐵→𝐷))≤(𝐴∨𝐵)→(𝐶∨𝐷), and (𝐴∨𝐵)→(𝐶∧𝐷)≤(𝐴→𝐶)∧(𝐵→𝐷).
Proof of Proposition 9.7 — Boolean laws and variance
Proof. The Boolean and product claims are the corresponding set identities. For variance, a graph constrained on every 𝐴 input is constrained on the smaller set 𝐴′, and every permitted 𝐵 output is a 𝐵′ output. For (9.4), an entry whose input is in 𝐴∨𝐵 satisfies at least one arrow constraint, so its output lies in 𝐶∨𝐷. Formula (9.5) follows twice by variance. ◻
Neither inclusion is generally an equality. With disjoint nonempty 𝐴,𝐵,𝐶,𝐷, a graph mapping an 𝐴 input to a 𝐷 output inhabits (𝐴∨𝐵)→(𝐶∨𝐷) but not 𝐴→𝐶, disproving the converse of (9.4). A graph mapping an 𝐴 input to 𝐶 and a 𝐵 input to 𝐷 inhabits (𝐴→𝐶)∧(𝐵→𝐷) but not (𝐴∨𝐵)→(𝐶∧𝐷), disproving the converse of (9.5). The empty graph inhabits every arrow; cardinality arguments about total mathematical functions therefore do not describe this model.
★★☆ Prove (9.4) directly from graph membership. Then use four pairwise-disjoint nonempty types, for example 𝖭𝖺𝗍, 𝖡𝗈𝗈𝗅, 𝖴𝗇𝗂𝗍, and 𝖭𝖺𝗍×𝖭𝖺𝗍, to construct a counterexample to its converse.
A normal form 𝜏 is a finite set of pairs (𝑃,𝑁) of finite sets of atoms. Its interpretation is [[𝜏]]=⋃(𝑃,𝑁)∈𝜏⎛⎜
⎜
⎜⎝⋂𝑎∈𝑃[[𝑎]]∖⋃𝑎∈𝑁[[𝑎]]⎞⎟
⎟
⎟⎠. Empty intersections denote 𝐷. Define mutually recursive functions N and ―――N by N(0)=∅,N(𝑎)={({𝑎},∅)},N(𝐴∨𝐵)=N(𝐴)∪N(𝐵),N(¬𝐴)=―――N(𝐴),―――N(0)={(∅,∅)},―――N(𝑎)={(∅,{𝑎})},―――N(¬𝐴)=N(𝐴). For union on the negative side, define ―――N(𝐴∨𝐵)={(𝑃1∪𝑃2,𝑁1∪𝑁2)∣(𝑃1,𝑁1)∈―――N(𝐴),(𝑃2,𝑁2)∈―――N(𝐵)}.
Proof. Simultaneous induction on 𝐴. For 𝐴=0, take the empty family of clauses; for an atom, the singleton clause has exactly the atom’s denotation. Union on the positive side is set union. On the negative side, clause pairing is justified by the explicit identity (⋂𝑃1∖⋃𝑁1)∩(⋂𝑃2∖⋃𝑁2)=⋂(𝑃1∪𝑃2)∖⋃(𝑁1∪𝑁2). Taking the union over all pairs of clauses gives the required complement of a union. Complement exchanges the two simultaneous induction hypotheses. ◻
It remains to decide whether a single clause is empty. If its positive atoms have two different shapes, it is empty because the three summands of 𝐷 are disjoint. Otherwise each possible runtime shape yields one obligation.
For fixed finite sets 𝑃,𝑁 of product atoms and 𝑁′⊆𝑁, write 𝐿(𝑃,𝑁′)=⋀𝐴×𝐵∈𝑃𝐴∧⋀𝐴×𝐵∈𝑁′¬𝐴,𝑅(𝑃,𝑁,𝑁′)=⋀𝐴×𝐵∈𝑃𝐵∧⋀𝐴×𝐵∈𝑁∖𝑁′¬𝐵.
Proof. For sets 𝑋𝑖,𝑌𝑖 use ⋂𝑖∈𝑃(𝑋𝑖×𝑌𝑖)∖⋃𝑖∈𝑁(𝑋𝑖×𝑌𝑖)=⋃𝑁′⊆𝑁⎛⎜
⎜
⎜⎝⋂𝑃𝑋𝑖∖⋃𝑁′𝑋𝑖⎞⎟
⎟
⎟⎠×⎛⎜
⎜
⎜
⎜⎝⋂𝑃𝑌𝑖∖⋃𝑁∖𝑁′𝑌𝑖⎞⎟
⎟
⎟
⎟⎠. A finite union of products is empty exactly when every product has an empty component. Interpreting the two components gives (9.7). ◻
For a concrete trace, normalize (𝖭𝖺𝗍×𝖡𝗈𝗈𝗅)∧¬(𝖭𝖺𝗍×𝖭𝖺𝗍). Here 𝑃={𝖭𝖺𝗍×𝖡𝗈𝗈𝗅} and 𝑁={𝖭𝖺𝗍×𝖭𝖺𝗍}. For 𝑁′=∅ the two components are 𝖭𝖺𝗍 and 𝖡𝗈𝗈𝗅∧¬𝖭𝖺𝗍=D𝖡𝗈𝗈𝗅, so neither is empty. For 𝑁′=𝑁 the left component is 𝖭𝖺𝗍∧¬𝖭𝖺𝗍=D0. Because the condition of lemma 9.11 fails at the first subset, the whole type is nonempty; (𝗓𝖾𝗋𝗈,𝗍𝗋𝗎𝖾) is a witness. This is the complete product calculation before the additional failure edge Ω enters the arrow case.
The function-shape clause determined by 𝑃,𝑁 is empty exactly when there is an 𝐴0→𝐵0∈𝑁 such that, for every 𝑃′⊆𝑃, DomOb(𝑃′)=D0or(𝑃′≠𝑃andCodOb(𝑃′)=D0).
Proof. An arrow denotes the finite powerset of the complement, taken inside 𝐷×𝐷Ω, of [[𝐴]]×(𝐷Ω∖[[𝐵]]). For finite families, ⋂𝑖∈𝑃P𝑓(𝑋𝑖)⊆⋃𝑗∈𝑁P𝑓(𝑋𝑗)⟺some𝑗∈𝑁satisfies⋂𝑖∈𝑃𝑋𝑖⊆𝑋𝑗. If some 𝑗 works, the right-hand inclusion immediately implies the left. Conversely, if no 𝑗 works, choose one witness outside each 𝑋𝑗; the finite set of witnesses belongs to every P𝑓(𝑋𝑖) but to none of the P𝑓(𝑋𝑗), contradicting the left-hand inclusion. Expanding the chosen inclusion says that every bad edge for 𝐴0→𝐵0 must be bad for some positive arrow: [[𝐴0]]×(𝐷Ω∖[[𝐵0]])⊆⋃𝐴𝑖→𝐵𝑖∈𝑃[[𝐴𝑖]]×(𝐷Ω∖[[𝐵𝑖]]). Suppose an edge (𝑑,𝛿) is uncovered, and define its exact miss set 𝑀={𝐴𝑖→𝐵𝑖∈𝑃∣𝑑∉[[𝐴𝑖]]}. Then 𝑑∈[[DomOb(𝑀)]]. If 𝑀≠𝑃, the uncoveredness condition forces 𝛿 to be an ordinary output in every 𝐵𝑖 with 𝑖∉𝑀, so 𝛿∈[[CodOb(𝑀)]]. If 𝑀=𝑃, the obligation at 𝑃′=𝑃 is only DomOb(𝑃)=D0, and 𝑑 refutes it; no codomain witness is required. Equivalently, pairing 𝑑 with Ω supplies an uncovered edge because Ω belongs to no positive codomain.
Conversely, fix any 𝑃′⊆𝑃. A witness 𝑑 for its domain obligation misses every positive arrow in 𝑃′. When 𝑃′≠𝑃, an ordinary witness 𝛿 for its codomain obligation belongs to every remaining positive codomain. Hence no positive arrow covers (𝑑,𝛿). For 𝑃′=𝑃, pair 𝑑 with Ω, which belongs to no positive codomain. In either case the edge violates (9.11). Thus the cover holds exactly when every 𝑃′ has empty DomOb(𝑃′), or has 𝑃′≠𝑃 and empty CodOb(𝑃′), which is (9.9). ◻
★★☆ Specialize (9.9) to prove (𝐴1→𝐵1)∧(𝐴2→𝐵2)≤𝐴→𝐵 exactly when all four subset rows induced by 𝑃′⊆{1,2} close. State the rows explicitly; the row 𝑃′={1,2} has only a domain obligation.
Let 𝑃,𝑁 be finite sets of basic atoms. Their clause is empty at basic shape exactly when ⋂𝑏∈𝑃𝐵𝑏⊆⋃𝑏∈𝑁𝐵𝑏, where the empty positive intersection is the basic summand 𝐶, not the whole domain 𝐷. This condition is decidable.
Proof. Intersecting the positive basic denotations and removing the union of the negative ones is empty exactly when the displayed inclusion holds. The fixed family of basic tags is finite and pairwise disjoint, so the inclusion reduces to a finite tag-membership test. ◻
The algorithm is memoized downward recursion. The equivalent finite-simulation presentation gives a table containing all mutually dependent emptiness obligations rather than only those reached from one query.
Let 𝑄 contain every atom occurring in a query normal form, including atoms nested inside product and arrow atoms. It is finite. Let NF(𝑄)=P𝑓(P𝑓(𝑄)×P𝑓(𝑄)). For a shape 𝑘, let 𝑄𝑘 be the atoms of 𝑄 having shape 𝑘. For 𝑆⊆NF(𝑄), say that a clause (𝑃,𝑁) is 𝑆-empty at a shape as follows.
At basic shape, the intersection of the positive tag sets is covered by the negative tag sets. With no positive basic atom, the intersection here is the whole basic summand 𝐶=⋃𝑏𝐵𝑏, not the whole domain 𝐷. The family of tag names is finite and disjoint, and tag coverage is decidable even when a tag contains infinitely many constants.
At product shape, every 𝑁′⊆𝑁 satisfies N(𝐿(𝑃,𝑁′))∈𝑆 or N(𝑅(𝑃,𝑁,𝑁′))∈𝑆.
At function shape, some 𝐴0→𝐵0∈𝑁 satisfies, for every 𝑃′⊆𝑃, either N(DomOb(𝑃′))∈𝑆, or 𝑃′≠𝑃 and N(CodOb(𝑃′))∈𝑆.
A normal form 𝜏 is an immediate consequence of 𝑆 when, for each clause (𝑃,𝑁)∈𝜏 and each shape 𝑘, either 𝑃 contains an atom of a different shape or (𝑃,𝑁∩𝑄𝑘) is 𝑆-empty at shape 𝑘. A set 𝑆 is a simulation when every member of 𝑆 is an immediate consequence of 𝑆.
A simulation is a finite table of claims that normal forms are empty. A row may justify itself only through component claims already in the table. For example, the singleton table {N(𝖭𝖺𝗍∧¬𝖭𝖺𝗍)} is a simulation: its one basic-shape row is closed by tag coverage. The greatest simulation is exactly the set of empty normal forms: soundness excludes an element from every row, while completeness places each empty component obligation back in the table.
Every component obligation uses an atom in 𝑄. Closing 𝑄 under the atoms nested in products and arrows therefore keeps the simulation table finite and closed under its own recursive obligations.
Proof. It is enough to prove that no 𝑑∈𝐷 belongs to a member of 𝑆. Induct on the finite construction of 𝑑. For a constant, the basic coverage condition excludes it. For (𝑑1,𝑑2), product decomposition selects, for every allocation of negative atoms, a component normal form in 𝑆; the induction hypothesis excludes 𝑑1 or 𝑑2. For a finite graph, clause (iii) gives an index 𝑗 and negative arrow 𝐶𝑗→𝐷𝑗. If the graph satisfies it, that negative atom excludes the graph. Otherwise an edge violates it. Apply (9.9) to that edge; the induction hypothesis excludes its strictly smaller input or output from the corresponding normal form. If the output is Ω, the codomain alternative is automatically excluded. Thus every runtime shape is absent from every clause. ◻
Proof. Take 𝑆0={𝜎∈NF(𝑄)∣[[𝜎]]=∅}. It contains 𝜏. Basic coverage and the two exact decomposition lemmas show that every clause in every 𝜎∈𝑆0 satisfies the corresponding immediate-consequence condition with component normal forms again in 𝑆0. Shapes are disjoint, so a positive atom of another shape closes the remaining cases. Hence 𝑆0 is a simulation. ◻
Proof of Theorem 9.16 — Emptiness and semantic subtyping are decidable
Proof. Compute 𝜏=N(𝐴) and use the following memoized recursive test on its clauses. A clause is empty when it is empty at every runtime shape. For a candidate shape 𝑘, the clause is immediately empty at 𝑘 if it contains a positive atom whose shape is not 𝑘. At basic shape, apply lemma 20.11, restricting negative atoms to the basic shape and using 𝐶 for an empty positive family. At product shape, enumerate 𝑁′⊆𝑁 and recursively test whether N(𝐿(𝑃,𝑁′)) or N(𝑅(𝑃,𝑁,𝑁′)) is empty. At function shape, try each negative arrow and, for every 𝑃′⊆𝑃, recursively test the domain obligation or the permitted codomain obligation from (9.9). A normal form is empty exactly when all of its clauses are empty. Cache answers by normalized syntax.
Every recursive obligation strictly decreases the multiset of depths of its nested product or arrow atoms, so this is a total procedure on finite type trees. Basic coverage and the exact product and arrow decomposition lemmas prove its soundness and completeness by induction on that multiset. Equivalently, its accepted memo table is contained in a finite simulation by lemma 9.14, lemma 9.15. Decide 𝐴≤𝐵 by testing 𝐴∧¬𝐵 and using corollary 9.8. ◻
If 𝑞=|𝑄|, there are at most 4𝑞 clauses and 24𝑞 normal forms over 𝑄. Materializing the whole greatest- simulation table therefore gives only a finite decision proof, not a practical implementation. The memoized downward test above visits only obligations reached from the query, although its subset branching can still be exponential.
The overload inclusion from the opening can now be decided without guessing a graph. The following trace exhibits every recursive obligation made by the arrow clause.
Put 𝑁𝑡=𝖭𝖺𝗍, 𝐵𝑡=𝖡𝗈𝗈𝗅, and 𝑆𝑡=𝑁𝑡∨𝐵𝑡. To decide (𝑁𝑡→𝑁𝑡)∧(𝐵𝑡→𝐵𝑡)≤𝑆𝑡→𝑆𝑡, normalize the difference between the two sides. It is the one function-shape clause 𝑃={𝑁𝑡→𝑁𝑡,𝐵𝑡→𝐵𝑡},𝑁−={𝑆𝑡→𝑆𝑡}. Its nested-atom closure is 𝑄={𝑁𝑡,𝐵𝑡,𝑁𝑡→𝑁𝑡,𝐵𝑡→𝐵𝑡,𝑆𝑡→𝑆𝑡}. The sole negative arrow fixes 𝐴0=𝐵0=𝑆𝑡. Choose 𝑃′⊆𝑃. Then lemma 9.12 asks whether DomOb(𝑃′) is empty or, when 𝑃′≠𝑃, whether CodOb(𝑃′) is empty. The four calculations are 𝑃′DomOb(𝑃′)CodOb(𝑃′)∅𝑆𝑡¬𝑆𝑡∧𝑁𝑡∧𝐵𝑡=D0{𝑁𝑡→𝑁𝑡}𝐵𝑡¬𝑆𝑡∧𝐵𝑡=D0{𝐵𝑡→𝐵𝑡}𝑁𝑡¬𝑆𝑡∧𝑁𝑡=D0𝑃𝑆𝑡∧¬𝑁𝑡∧¬𝐵𝑡=D0notavailable. The first row closes because 𝑁𝑡∧𝐵𝑡=D0; the next two close because 𝐵𝑡≤𝑆𝑡 and 𝑁𝑡≤𝑆𝑡, respectively; the final row closes on its domain component. The difference is empty, so the requested inclusion holds. If both component obligations in one row are nonempty, choose an uncovered input and output; their one-edge graph is a finite counterexample.
★★☆ Use the trace of example 9.17 to decide (𝖭𝖺𝗍→𝖭𝖺𝗍)∧(𝖡𝗈𝗈𝗅→𝖡𝗈𝗈𝗅)≤(𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅)→𝖭𝖺𝗍. Identify the first row in which neither component is empty, and construct the one-edge graph witnessing failure of the inclusion.
The semantic relation can safely drive application, but only with an explicit callability premise. The function-shape top 0→1 alone is not enough: it contains graphs that fail with Ω on every nonempty domain.
Runtime tests contain no precise arrow atoms: 𝑈,𝑉::=0∣1∣𝑏∣𝖥𝗎𝗇∣𝑈×𝑉∣𝑈∨𝑉∣𝑈∧𝑉∣¬𝑈,𝖥𝗎𝗇:=0→1. Terms and values are 𝑒::=𝑐∣𝑥∣(𝑒,𝑒)∣𝜋𝑖𝑒∣𝜆(𝐴1→𝐵1;…;𝐴𝑛→𝐵𝑛)𝑥.𝑒∣𝑒𝑒∣𝖼𝖺𝗌𝖾𝖳𝗒𝗉𝖾𝑒𝖺𝗌𝑥𝗂𝗇𝑈⇒𝑒∣𝑒,𝑣::=𝑐∣(𝑣,𝑣)∣𝜆(𝐴1→𝐵1;…;𝐴𝑛→𝐵𝑛)𝑥.𝑒. Interfaces are nonempty and denote 𝐼=⋀𝑖(𝐴𝑖→𝐵𝑖). The grammar above makes the well-shapedness condition of definition 9.1 syntactic: an interface has one arbitrary domain, or all its domains are test types. This admits the single-arrow self-application example and the multi-arrow 𝖭𝖺𝗍/𝖡𝗈𝗈𝗅 overload while keeping finite branch selection structural.
The restriction excludes the tempting two-arrow interface whose domains are 1→1 and ¬(1→1). Although 𝖥𝗎𝗇≤(1→1)∨¬(1→1), a lambda known only at 𝖥𝗎𝗇 need be typable at neither arm. For that interface, neither branch judgment required by beta preservation is derivable. The tautology 𝖥𝗎𝗇≤1 proves only membership in the universal type, not either proposed arm.
The decidable judgment 𝑣⊩𝑈, read “𝑣 passes test 𝑈,” is defined by the following exhaustive clauses: 𝑣⊩0never,𝑣⊩1always,𝑣⊩𝑏⟺𝑣=𝑐and𝑐∈𝐵𝑏,𝑣⊩𝖥𝗎𝗇⟺𝑣=𝜆𝐼𝑥.𝑒,𝑣⊩𝑈×𝑉⟺𝑣=(𝑣1,𝑣2),𝑣1⊩𝑈,and𝑣2⊩𝑉,𝑣⊩𝑈∨𝑉⟺𝑣⊩𝑈or𝑣⊩𝑉,𝑣⊩𝑈∧𝑉⟺𝑣⊩𝑈and𝑣⊩𝑉,𝑣⊩¬𝑈⟺𝑣⊮𝑈. The shape equations make a pair fail every basic and 𝖥𝗎𝗇 test, a constant fail every product and 𝖥𝗎𝗇 test, and an abstraction fail every basic and product test.
For example, 𝗓𝖾𝗋𝗈∈𝐵𝖭𝖺𝗍 and 𝗍𝗋𝗎𝖾∈𝐵𝖡𝗈𝗈𝗅, so the membership derivation is 𝗓𝖾𝗋𝗈∈𝐵𝖭𝖺𝗍𝗓𝖾𝗋𝗈⊩𝖭𝖺𝗍M−Basic𝗍𝗋𝗎𝖾∈𝐵𝖡𝗈𝗈𝗅𝗍𝗋𝗎𝖾⊩𝖡𝗈𝗈𝗅M−Basic(𝗓𝖾𝗋𝗈,𝗍𝗋𝗎𝖾)⊩𝖭𝖺𝗍×𝖡𝗈𝗈𝗅M−Pair. The labels M-Basic and M-Pair name the basic-constant and pair instances of the structural equations; they are decision clauses, not typing rules.
Consequently the selected branch is determined before substitution, and the complete root trace is 𝖼𝖺𝗌𝖾𝖳𝗒𝗉𝖾(𝗓𝖾𝗋𝗈,𝗍𝗋𝗎𝖾)𝖺𝗌𝑥𝗂𝗇𝖭𝖺𝗍×𝖡𝗈𝗈𝗅⇒𝜋1𝑥∣𝖿𝖺𝗅𝗌𝖾⟶𝜋1(𝗓𝖾𝗋𝗈,𝗍𝗋𝗎𝖾)⟶𝗓𝖾𝗋𝗈. No typing derivation is consulted by either step.
The role of Ω is exact. An edge (𝑑,Ω) records failure on 𝑑 and excludes its graph from 𝐴→𝐵 when 𝑑∈[[𝐴]]. On Ω-free graphs every 𝐴→1 constraint permits every result; on all graphs, 0→1 is the function-shape top. We therefore define a function type 𝐹 to be callable on a static argument type 𝑆 when 𝐹≤𝑆→1. Callability determines whether application is safe. Its least result type requires a separate calculation from the DNF clauses of 𝐹. For example, 0→1≰𝑆→1 when 𝑆 is nonempty.
The application calculation needs one closure fact about negative arrows.
Proof of Lemma 9.21 — Strong disjunction for a function clause
Proof. The right-to-left implication is subsumption because 𝐾≤𝐾+. Conversely, suppose 𝐾≤𝑆→𝑅 but choose a finite graph 𝐺∈[[𝐾+]]∖[[𝑆→𝑅]]. Since 𝐾 is nonempty, choose 𝐻∈[[𝐾]]. The union 𝐺∪𝐻 still satisfies every positive arrow: those conditions are universal over edges. For each negative arrow in the clause, 𝐻 already has an edge that violates it, and adjoining edges cannot remove that witness. Thus 𝐺∪𝐻∈[[𝐾]]. The edge by which 𝐺 violates 𝑆→𝑅 also remains, so 𝐺∪𝐻∉[[𝑆→𝑅]], a contradiction. ◻
Assume 𝐹≤0→1. Normalize 𝐹∧(0→1) to function-shape clauses. The conjunct 0→1 forces every surviving clause into the function shape, so the domain and output constructions below never face a basic or product clause. It does not otherwise refine 𝐹, because the premise already gives 𝐹=D𝐹∧(0→1). For a nonempty clause with positive-arrow set 𝑃𝑐={𝐴𝑖→𝐵𝑖∣𝑖∈𝐾𝑐} put Dom𝑐(𝑃𝑐)=⋁𝑖∈𝐾𝑐𝐴𝑖,𝜌𝑐(𝑃𝑐)=⎧{
{⎨{
{⎩⎛⎜
⎜
⎜
⎜⎝⋁𝑖∈𝐾′𝐴𝑖,⋀𝑖∈𝐾𝑐∖𝐾′𝐵𝑖⎞⎟
⎟
⎟
⎟⎠∣
∣
∣
∣
∣
∣𝐾′⊊𝐾𝑐⎫{
{⎬{
{⎭. For a finite union of clauses, define Dom∗(𝐹) by intersecting the Dom𝑐 types of the nonempty clauses, and define 𝜌∗(𝐹) by uniting their 𝜌𝑐 sets. The empty union has Dom∗(0)=1 and 𝜌∗(0)=∅. When 𝐹≤𝑆→1, define 𝐹∘𝑆=⋁(𝑈,𝑉)∈𝜌∗(𝐹),𝑆≰𝑈𝑉. The circle is an operation on types; it does not compose terms. Negative arrow atoms affect whether a clause is empty, but lemma 9.21 shows that they do not change its arrow supertypes once the clause is known nonempty.
Proof of Lemma 9.23 — Application-output characterization
Proof. Fix a nonempty clause 𝑐. By lemma 9.21, its negative arrows may be discarded when checking the supertype 𝑆→𝐵. Apply lemma 9.12 to the remaining positive arrows and the one negative arrow 𝑆→𝐵. At a subset 𝐾′⊆𝐾𝑐, its two emptiness tests translate exactly as 𝑆∧⋀𝑖∈𝐾′¬𝐴𝑖=D0⟺𝑆≤⋁𝑖∈𝐾′𝐴𝑖,¬𝐵∧⋀𝑖∈𝐾𝑐∖𝐾′𝐵𝑖=D0⟺⋀𝑖∈𝐾𝑐∖𝐾′𝐵𝑖≤𝐵. For 𝐾′=𝐾𝑐, arrow decomposition permits only the first test; this is 𝑆≤Dom𝑐(𝑃𝑐). The proper subsets give precisely the pairs in 𝜌𝑐(𝑃𝑐). Finally, 𝐹≤𝑆→𝐵 holds exactly when every nonempty clause has this property. Intersecting their domain types and uniting their proper-subset pairs therefore gives 𝐹≤𝑆→𝐵⟺𝑆≤Dom∗(𝐹)∧∀(𝑈,𝑉)∈𝜌∗(𝐹).𝑆≤𝑈∨𝑉≤𝐵. The callability premise is precisely the domain conjunct. The remaining finite family says that every 𝑉 whose 𝑈 fails to cover 𝑆 is below 𝐵, which is equivalent to their union (9.13) being below 𝐵. DNF, emptiness, and every comparison are computable by theorem 9.16. ◻
Let 𝐼=(𝖭𝖺𝗍→𝖭𝖺𝗍)∧(𝖡𝗈𝗈𝗅→𝖡𝗈𝗈𝗅). Because 𝐼≤0→1, the normalized conjunct 𝐼∧(0→1) is equivalent to 𝐼; we use this simplified representative. Its one positive-arrow clause has index set 𝐾𝑐={𝑁,𝐵}. The three proper subsets of 𝐾𝑐 give 𝜌∗(𝐼)={(0,𝖭𝖺𝗍∧𝖡𝗈𝗈𝗅),(𝖭𝖺𝗍,𝖡𝗈𝗈𝗅),(𝖡𝗈𝗈𝗅,𝖭𝖺𝗍)}. The basic tags are disjoint, so the first output is 0. Applying (9.13) three times yields 𝐼∘𝖭𝖺𝗍𝜌∗𝑟𝑜𝑤(𝖡𝗈𝗈𝗅,𝖭𝖺𝗍)=𝖭𝖺𝗍,𝐼∘𝖡𝗈𝗈𝗅𝜌∗𝑟𝑜𝑤(𝖭𝖺𝗍,𝖡𝗈𝗈𝗅)=𝖡𝗈𝗈𝗅,𝐼∘(𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅)𝑏𝑜𝑡ℎ𝑠𝑖𝑛𝑔𝑙𝑒𝑡𝑜𝑛𝑟𝑜𝑤𝑠=𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅. Thus a precise argument retains its corresponding promise, while an imprecise argument returns exactly the union of the two results.
Projection has a simpler clausewise definition. Normalize 𝐴×∧(1×1) and consider one nonempty product-shape clause with positive product atoms 𝑃𝑐 and negative product atoms 𝑁𝑐. Using (9.6), we make the construction explicit.
For one nonempty product-shape clause define out1(𝑃𝑐,𝑁𝑐)=⋁𝑁′⊆𝑁𝑐𝑅(𝑃𝑐,𝑁𝑐,𝑁′)≠D0𝐿(𝑃𝑐,𝑁′),out2(𝑃𝑐,𝑁𝑐)=⋁𝑁′⊆𝑁𝑐𝐿(𝑃𝑐,𝑁′)≠D0𝑅(𝑃𝑐,𝑁𝑐,𝑁′). The empty join is 0. Let proj𝑖(𝐴×) be the union of out𝑖 over all nonempty clauses.
Proof of Lemma 9.25 — Projection-output characterization
Proof. The product decomposition writes each clause as the union, over 𝑁′⊆𝑁𝑐, of the rectangles 𝐿(𝑃𝑐,𝑁′)×𝑅(𝑃𝑐,𝑁𝑐,𝑁′). Its first-coordinate image is therefore the union of the left components whose right component is nonempty, exactly out1; the second-coordinate statement is symmetric. Inclusion of that finite union in 𝐴 is equivalent to inclusion of the whole clause in 𝐴×1. Taking the union over clauses proves both equivalences. Every emptiness test and finite union is computable by theorem 9.16. ◻
The typing relation is generated by the three rules of definition 9.1, the following application and subsumption rules, and four rules for constants, pairs, projections, and typecase. Each abstraction interface must be well shaped in the sense of definition 9.1. Contexts are lists of pairwise distinct term variables, and extending Γ by 𝑥:𝐴 presupposes 𝑥∉dom(Γ). A judgment Γ⊢𝑒:𝐴 is formed only when fv(𝑒)⊆dom(Γ), treating the abstraction and typecase binders as binders.
The two explicit scope premises in T-Case remain mandatory even when an empty refinement suppresses a branch’s typing premise. Each implication in T-Case is a decidable rule schema. When its antecedent is true, the consequent is an ordinary premise and a rule-induction proof receives an induction hypothesis for it; when false, there is no such premise. Thus an empty refinement suppresses only its branch-typing premise, not the explicit scope check on the branch syntax. There is no general principle that arbitrary syntax becomes typable merely because a context contains an empty assumption.
For 𝐼=(𝐴1→𝐵1;…;𝐴𝑛→𝐵𝑛), rule T-Abs concludes exactly ⋀𝑖(𝐴𝑖→𝐵𝑖); no negative arrow occurs in its conclusion. Thus intersection introduction and least-type synthesis use the same positive interface. By lemma 9.23, the least conclusion of T-App is 𝐹∘𝑆: its premise 𝐹≤𝑆→𝐵 implies both 𝐹≤0→1 and 𝐹≤𝑆→1, and the characterization then gives 𝐹∘𝑆≤𝐵. Every other conclusion follows from the least one by subsumption.
The following transformations are admissible for the typing judgment of definition 9.26: whenever their premises are derivable, so are their conclusions.
If Γ′ has the same domain as Γ and Γ′(𝑥)≤Γ(𝑥) pointwise, every judgment under Γ remains derivable under Γ′.
If Γ⊢𝑒:𝐵 and 𝑦∉dom(Γ), then Γ,𝑦:𝐶⊢𝑒:𝐵.
If Γ,𝑥:𝐴,Δ⊢𝑒:𝐵 and Γ⊢𝑣:𝐴, then Γ,Δ⊢𝑒[𝑣/𝑥]:𝐵. The usual substitution statement is the case Δ=⋅.
Proof. Each clause is an induction on its typing derivation.
For narrowing, the induction hypothesis says that each immediate typing premise remains derivable after replacing the outer context by its pointwise smaller context. In the variable case, if 𝑦:𝐶∈Γ and Γ′(𝑦)=𝐶′≤𝐶, then T-Var gives Γ′⊢𝑦:𝐶′ and T-Sub gives Γ′⊢𝑦:𝐶. Constants have no typing premise. Pair, projection, application, intersection, and subsumption reapply their rule to the induction hypotheses; their semantic side conditions mention types, not the context. For T-Abs, extend both contexts by the same 𝑥:𝐴𝑖 and apply the induction hypothesis separately to each body derivation. For T-Case, extend both contexts by the same 𝑥:𝑆∧𝑈 or 𝑥:𝑆∧¬𝑈. The nonemptiness tests and the two scope premises are unchanged because the domains of Γ and Γ′ agree. Thus narrowing preserves both branch derivations of T-Case, including their nonemptiness and scope premises.
For weakening, induct again on the last rule. Constants and variables reapply their rules in the extended context, and each nonbinding constructor uses the induction hypotheses for its immediate subterms. Before an abstraction or typecase case, alpha-rename its binder away from the fresh variable 𝑦; then apply the induction hypothesis under the extended binder. The scope premise for a typecase remains true because its permitted domain has only grown.
For substitution, the induction hypothesis is the exact assertion Γ,𝑥:𝐴,Δ⊢𝑒:𝐶,Γ⊢𝑣:𝐴⟹Γ,Δ⊢𝑒[𝑣/𝑥]:𝐶, where all types are unchanged because this calculus has no type variables. If 𝑒=𝑥, use the assumed derivation Γ⊢𝑣:𝐴; if 𝑒=𝑦≠𝑥, reapply T-Var to the unchanged declaration of 𝑦. Constants are unchanged. Pair, projection, application, intersection, and subsumption apply the induction hypothesis to each term premise and then reapply the same rule.
For an abstraction with binder 𝑧, alpha-rename so that 𝑧≠𝑥 and 𝑧∉fv(𝑣). Apply the induction hypothesis directly with suffix Δ,𝑧:𝐴𝑖; its value premise remains the assumed Γ⊢𝑣:𝐴, and its conclusion has context Γ,Δ,𝑧:𝐴𝑖. Then T-Abs rebuilds the abstraction. The typecase binder is handled identically, once under 𝑧:𝑆∧𝑈 and once under 𝑧:𝑆∧¬𝑈. Its conditional branch premises are unchanged because substitution does not alter 𝑆 or 𝑈. Finally, the elementary scope-substitution fact fv(𝑒)⊆dom(Γ)∪{𝑥}⟹fv(𝑒[𝑣/𝑥])⊆dom(Γ) preserves both explicit branch-scope premises. Thus Γ,𝑥:𝐴,Δ⊢𝑒:𝐶 and Γ⊢𝑣:𝐴 imply Γ,Δ⊢𝑒[𝑣/𝑥]:𝐶. ◻
For preservation we need to recover what a value’s outer constructor actually introduced, before subsumption obscured it.
For a value whose annotations and bodies typecheck, define vt(𝑐):=𝑏𝑐,vt((𝑣1,𝑣2)):=vt(𝑣1)×vt(𝑣2),vt(𝜆𝐼𝑥.𝑒):=𝐼, where the disjoint basic tags determine the unique 𝑏𝑐 containing 𝑐.
Proof. Induct on the typing derivation. Rules T-Const, T-Pair, and T-Abs give the three exact types and the displayed inversion data. For T-Sub, compose the induction-hypothesis inclusion with its subtype premise. For T-Inter, the two induction hypotheses have the same value syntax and hence the same exact type; combine their inclusions into the intersection. No other typing rule concludes with value syntax.
Nonemptiness is by value shape. The actual constant 𝑐 inhabits its tag; the pair of witnesses inhabits the product; and the empty finite graph inhabits every arrow in a nonempty interface, hence their intersection. ◻
If Γ⊢𝑣:𝑆, then for every test type 𝑈, 𝑣⊩𝑈⇒vt(𝑣)≤𝑈andΓ⊢𝑣:𝑆∧𝑈,𝑣⊮𝑈⇒vt(𝑣)≤¬𝑈andΓ⊢𝑣:𝑆∧¬𝑈. No value has type 0. A value at a type below 1×1 is a pair, and a value at a type below 0→1 is an annotated abstraction.
Proof of Lemma 9.30 — Value refinement and canonical forms
Proof. Induct simultaneously on the value and test type to prove vt(𝑣)≤𝑈 when 𝑣⊩𝑈, and vt(𝑣)≤¬𝑈 otherwise. Basic tags use disjointness; product tests use the two component hypotheses; and the 𝖥𝗎𝗇 test uses the annotated-abstraction shape. Boolean cases are the corresponding set identities. Combine either inclusion with lemma 9.29 and subsume to the required intersection.
If Γ⊢𝑣:0, exact value typing would put the nonempty vt(𝑣) below 0, a contradiction. Finally, the three principal value shapes occupy disjoint summands of 𝐷; exact value typing therefore proves the pair and abstraction canonical forms. ◻
Union is a control-flow join
Subtyping introduces a union without changing the value. The following two rules are derived instances of T-Sub, using 𝐴≤𝐴∨𝐵 and 𝐵≤𝐴∨𝐵:
Γ⊢𝑒:𝐴
Γ⊢𝑒:𝐴∨𝐵
_1
Γ⊢𝑒:𝐵
Γ⊢𝑒:𝐴∨𝐵
_2
Unlike 𝐴+𝐵, the type 𝐴∨𝐵 adds no injection tag. The runtime must test a property already possessed by the value.
For the binder typecase of definition 9.18, if 𝑒:𝑆, the then branch receives 𝑥:𝑆∧𝑈 and the else branch receives 𝑥:𝑆∧¬𝑈. In particular, if 𝑆=𝐴∨𝐵 and the test is 𝐴, the else type is (𝐴∨𝐵)∧¬𝐴=D𝐵∧¬𝐴 and is not generally 𝐵. If 𝐵≤𝐴, the else refinement is 0, so rule T-Case has no typing premise for that branch. A value selecting the else branch would have type 0 by lemma 9.30, which is impossible. If 𝐴 and 𝐵 overlap, the refinement contains only the part of 𝐵 outside 𝐴.
The binder matters. Refining a freely repeated expression would require a proof that every occurrence denotes the same runtime result. The binder names the already evaluated value once and makes that equality syntactic.
From 𝑒:𝐴∨𝐵 one cannot choose an 𝐴 branch or a 𝐵 branch merely by inspecting the syntax by which 𝑒 was typed. Subsumption can assign 𝐴∨𝐵 to the same value using either inclusion, and an intersection value may inhabit both arms. The typing derivation is erased at runtime. A sum value, by contrast, contains either 𝗂𝗇𝗅 or 𝗂𝗇𝗋. Typecase therefore uses the decidable structural test of definition 9.19; it is not the eliminator for a tagged sum.
By (9.4), (𝖭𝖺𝗍→𝖭𝖺𝗍)∧(𝖡𝗈𝗈𝗅→𝖡𝗈𝗈𝗅)≤(𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅)→(𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅). This inclusion is precisely the last premise of T-App. With 𝐼 for the left side and 𝑆=𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅, the complete last step is 𝑧:𝑆⊢𝗌𝖺𝗆𝖾:𝐼𝑧:𝑆∈𝑧:𝑆𝑧:𝑆⊢𝑧:𝑆T−Var𝐼≤𝑆→𝑆𝑧:𝑆⊢𝗌𝖺𝗆𝖾𝑧:𝑆T−App. A binder typecase gives a second derivation: it refines 𝑧 to 𝖭𝖺𝗍 or 𝖡𝗈𝗈𝗅, obtains the corresponding result in each branch, and joins them. By lemma 9.23, the least output is 𝐼∘𝑆=𝑆.
Intersection also types a genuine self occurrence. Put 𝐴=0→1,𝑋=((𝐴→1)∧𝐴). The type 𝑋 is nonempty: the empty finite graph inhabits both arrow atoms. Under 𝑥:𝑋, both occurrences synthesize 𝑋. We have 𝑋≤0→1 and 𝑋≤𝑋→1: the latter follows from 𝑋≤𝐴→1 and 𝑋≤𝐴. Thus T-App gives 𝑥:𝑋⊢𝑥:𝑋𝑥:𝑋⊢𝑥:𝑋𝑋≤𝑋→1𝑥:𝑋⊢𝑥𝑥:1T−App. Consequently 𝜆(𝑋→1)𝑥.𝑥𝑥:𝑋→1 is admitted without a recursive type equation. This is self-application inside the body, not the divergent term obtained by applying the abstraction to itself.
★☆☆ Starting from the T-Abs derivation of 𝗌𝖺𝗆𝖾:(𝖭𝖺𝗍→𝖭𝖺𝗍)∧(𝖡𝗈𝗈𝗅→𝖡𝗈𝗈𝗅), use subsumption to derive each arrow type separately. Then apply T-Inter to reconstruct its intersection type without using T-Abs a second time.
★☆☆ Let 𝑆=𝐴∨𝐵. Compute both refinements for a test against 𝐴. Give one choice of 𝐴,𝐵 for which the else branch is empty and one for which it is a proper subtype of 𝐵.
★☆☆ Return to the self-application derivation of example 20.32. Verify every subtype premise using the Boolean intersection eliminations and arrow variance of proposition 9.7.
Proof. If the interface has one arrow 𝐴1→𝐵1, the value derivation Γ⊢𝑣:𝑆 and the no-0-value clause of lemma 9.30 imply 𝑆≠D0. If some 𝑑 lay in [[𝑆∖𝐴1]], the graph {(𝑑,Ω)} would inhabit 𝐴1→𝐵1 but not 𝑆→𝑅; hence 𝑆≤𝐴1. Choose 𝑑∈[[𝑆]]. If some 𝑟∈[[𝐵1∖𝑅]], the ordinary-output graph {(𝑑,𝑟)} would again inhabit 𝐴1→𝐵1 but not 𝑆→𝑅; hence 𝐵1≤𝑅. Substitution therefore types the body at 𝐵1, followed by subsumption.
Otherwise every 𝐴𝑖 is a test type. Arrow decomposition gives 𝑆≤⋁𝑖𝐴𝑖. Put 𝐽={𝑖∣𝑣⊩𝐴𝑖}. This set is nonempty: otherwise exact value refinement would put the nonempty vt(𝑣) below the complement of every 𝐴𝑖, contradicting vt(𝑣)≤𝑆. In the 𝜌∗(𝐼) obligation of definition 9.22, take 𝐾′=𝐾𝑐∖𝐽. The exact value type is disjoint from ⋁𝑖∈𝐾′𝐴𝑖, so 𝑆≰⋁𝑖∈𝐾′𝐴𝑖; the other half of that obligation is therefore ⋀𝑖∈𝐽𝐵𝑖≤𝑅. For each 𝑖∈𝐽, (9.16) and subsumption type Γ⊢𝑣:𝐴𝑖; the corresponding T-Abs premise and substitution type the body at 𝐵𝑖. Rule T-Inter combines the derivations, and subsumption gives 𝑅. ◻
The value-shape step in this lemma is the local restriction inherited from the finite calculus: annotated values admit the finite Boolean split needed by an interface. It is not a claim of occurrence completeness for arbitrary open expressions.
Proof. Induct on the final typing rule. The induction hypothesis for an immediate premise Γ⊢𝑒0:𝐶 says that every step 𝑒0⟶𝑒′0 preserves exactly 𝐶.
First consider contextual steps. From Γ⊢(𝑒1,𝑒2):𝐴1×𝐴2, the last-rule premises type both components. If 𝑒1⟶𝑒′1, the induction hypothesis and T-Pair type ⟨𝑒′1,𝑒2⟩; if 𝑒1 is a value and 𝑒2⟶𝑒′2, they type ⟨𝑒1,𝑒′2⟩. Rules T-Proj and T-Case use the induction hypothesis for their scrutinee. Rule T-App uses it first for the function and then, when the function is a value, for the argument. In every case the semantic side conditions are unchanged. A step below T-Sub is followed by the same subsumption. A step below T-Inter is preserved by both induction hypotheses, after which T-Inter is reapplied. Constants, variables, and abstractions have no contextual step under the weak reduction of definition 9.20.
There remain four root families. For 𝜋1(𝑣1,𝑣2)⟶𝑣1, lemma 9.29 gives Γ⊢𝑣𝑖:𝐴𝑖 and 𝐴1×𝐴2≤𝑃, with both 𝐴𝑖 nonempty. Equation (9.15) gives 𝑃≤proj1(𝑃)×1. For every 𝑎1∈[[𝐴1]], choose 𝑎2∈[[𝐴2]]; the two product inclusions put (𝑎1,𝑎2) in [[proj1(𝑃)×1]]. Hence 𝐴1≤proj1(𝑃), and subsumption types the reduct. The second projection is symmetric.
For (𝜆𝐼𝑥.𝑒)𝑣⟶𝑒[𝑣/𝑥], inversion by lemma 9.29 recovers every premise Γ,𝑥:𝐴𝑖⊢𝑒:𝐵𝑖 and the inclusion 𝐼≤𝐹. Inversion of T-App gives 𝐹≤𝑆→𝐵; composing with 𝐼≤𝐹 gives 𝐼≤𝑆→𝐵. The result is exactly lemma 9.31 with 𝑅=𝐵.
For the then typecase root, (9.16) derives Γ⊢𝑣:𝑆∧𝑈. Exact value typing shows that this refinement is nonempty, so the conditional then premise of T-Case is derivable. Substitution gives Γ⊢𝑒+[𝑣/𝑥]:𝐵+, followed by subsumption to 𝐵+∨𝐵−. If the test fails, (9.16) gives Γ⊢𝑣:𝑆∧¬𝑈; substitution gives Γ⊢𝑒−[𝑣/𝑥]:𝐵−, followed by subsumption to the same union. ◻
Proof. Induct on the final typing rule, with induction hypothesis “the premise term is a value or it takes a step.” Constants and abstractions are values; a closed variable judgment is impossible. Subsumption does not change the term, so it uses its sole induction hypothesis. Intersection uses either premise, whose term is the same.
For a pair, step the left component if possible; if it is a value, step the right component; if both are values, the pair is a value. For a projection, first use the scrutinee induction hypothesis. If the scrutinee is a value, canonical forms from lemma 9.30 show that it is a pair, so one of the two projection roots applies.
For an application, first step its function, then its argument. If both are values, exact value typing gives a nonempty 𝑉=vt(𝑣) with 𝑉≤𝐹≤0→1. Canonical forms therefore show that the function value is an annotated abstraction. The beta root therefore applies. For typecase, first step the scrutinee. Once it is a value, the exhaustive clauses of definition 9.19 decide exactly one of 𝑣⊩𝑈 and 𝑣⊮𝑈, so exactly one typecase root applies.
For safety, induct on the length of a reduction sequence. Preservation types the first reduct at 𝐴; progress applies again to it. Thus no finite prefix can end in a closed stuck nonvalue. ◻
The theorem applies exactly to the weak call-by-value relation of definition 9.20. To see why, consider a hypothetical extension 𝗋𝗇𝖽(𝐴∨𝐵) that nondeterministically returns either an 𝐴-value or a 𝐵-value. If beta reduction duplicated this expression before evaluating it, the two copies in (𝜆𝑥.(𝑥,𝑥))𝗋𝗇𝖽(𝐴∨𝐵) could choose differently, so the result would no longer have the promised correlation type (𝐴×𝐴)∨(𝐵×𝐵). Likewise, if a pair (𝑣𝐴,𝑒0):𝐴×0 could be formed while 𝑒0 diverged and projection reduced before the second component became a value, 𝜋1(𝑣𝐴,𝑒0) would produce an 𝐴-value from a product type with no values. These counterexamples require nondeterminism or divergence, neither of which belongs to the local calculus.
Define the partial function synΓ(𝑒) by structural recursion. Constants return their basic tag, variables return their context type, and pairs return the product of component results. Projection of a synthesized 𝐴× succeeds when 𝐴×≤1×1 and returns proj𝑖(𝐴×).
For an abstraction with interface 𝐼=⋀𝑖(𝐴𝑖→𝐵𝑖), recursively reject first if the written interface is empty or is not well shaped according to definition 9.18. Otherwise recursively check its body under 𝑥:𝐴𝑖 against 𝐵𝑖 for every 𝑖, then return 𝐼. For application, synthesize 𝐹 and 𝑆; succeed exactly when 𝐹≤0→1 and 𝐹≤𝑆→1, then return 𝐹∘𝑆.
For typecase, first decide the two finite-variable scope premises of T-Case and reject if either fails, then synthesize 𝑆 for the scrutinee. An empty refinement contributes 0 without typechecking its branch; a nonempty refinement recursively synthesizes its branch under the refined binder. Return the union of the two branch results. Finally, checking 𝑒:𝐴 succeeds when synthesis returns some 𝑆≤𝐴.
Proof. Suppose synΓ(𝑒)=𝑆 and induct on 𝑒. Constants and variables use T-Const and T-Var; a pair uses the two induction hypotheses and T-Pair. For a projection, the recursive call gives Γ⊢𝑒0:𝑃, and the successful side condition gives 𝑃≤1×1, so T-Proj returns the stated output. For an abstraction, success entails nonemptiness and well-shapedness of the interface. For every arrow 𝐴𝑖→𝐵𝑖, the body induction returns 𝐶𝑖≤𝐵𝑖; subsumption checks that branch at 𝐵𝑖. Thus T-Abs returns exactly the written interface 𝐼.
For application, the recursive calls give Γ⊢𝑒1:𝐹 and Γ⊢𝑒2:𝑆0. The two successful side conditions meet the hypotheses of lemma 9.23, whose right-to-left direction gives 𝐹≤𝑆0→(𝐹∘𝑆0). Rule T-App therefore derives the returned type. For typecase, a nonempty refinement has a recursively synthesized branch, which the induction hypothesis types at its returned type. An empty refinement contributes 0 and activates no branch-typing premise. The scope checks and these two alternatives are exactly the premises of T-Case, so that rule derives the returned union. This proves synΓ(𝑒)=𝑆⟹Γ⊢𝑒:𝑆. ◻
Proof. Induct on a derivation of Γ⊢𝑒:𝐴. The constant, variable, and pair cases follow directly from the induction hypotheses. Under T-Sub, a synthesized 𝑆≤𝐴0 is below the new conclusion by transitivity. The two T-Inter premises concern the same syntax; the deterministic recursive function therefore returns the same 𝑆 for both, and 𝑆≤𝐴 and 𝑆≤𝐵 imply 𝑆≤𝐴∧𝐵.
For T-Proj, let 𝐴×,0 be the synthesized scrutinee type. The induction hypothesis gives 𝐴×,0≤𝐴×, hence 𝐴×,0≤1×1. From 𝐴×≤proj𝑖(𝐴×)×1 (with the factors exchanged for 𝑖=2) and 𝐴×,0≤𝐴×, the projection characterization yields proj𝑖(𝐴×,0)≤proj𝑖(𝐴×). Thus the synthesized projection type is below the declarative conclusion. In T-Abs, the declarative rule guarantees that the written interface is well shaped. Each body induction returns a subtype of its declared 𝐵𝑖, so synthesis returns exactly that interface 𝐼, with 𝐼≤𝐼.
For T-App, let the recursive calls return 𝐹0≤𝐹 and 𝑆0≤𝑆. The premise 𝐹≤𝑆→𝐵, arrow variance, and transitivity give 𝐹0𝐼𝐻≤𝐹𝑡𝑦𝑝𝑖𝑛𝑔𝑝𝑟𝑒𝑚𝑖𝑠𝑒≤𝑆→𝐵𝑆0≤𝑆𝑎𝑛𝑑𝑣𝑎𝑟𝑖𝑎𝑛𝑐𝑒≤𝑆0→𝐵𝐵≤1≤𝑆0→10≤𝑆0𝑎𝑛𝑑𝑣𝑎𝑟𝑖𝑎𝑛𝑐𝑒≤0→1. Thus both algorithmic callability checks succeed, and lemma 9.23 gives 𝐹0∘𝑆0≤𝐵.
For T-Case, if the synthesized scrutinee type is 𝑆0≤𝑆, context narrowing changes a branch premise under 𝑥:𝑆∧𝑈 to one under 𝑥:𝑆0∧𝑈. Replacing 𝑈 by ¬𝑈 gives the corresponding else-branch narrowing. If the new refinement is nonempty, the old one is also nonempty; the branch induction hypothesis therefore returns a subtype of 𝐵+ or 𝐵−. If the new refinement is empty, synthesis contributes 0, already below the corresponding branch type. The explicit scope premises ensure that its preliminary scope checks succeed. Hence the returned union is below 𝐵+∨𝐵−. Therefore Γ⊢𝑒:𝐴⟹synΓ(𝑒)=𝑆forsome𝑆≤𝐴. ◻
For finite annotated terms, including terms whose interfaces or free variables may be rejected, Γ⊢𝑒:𝐴⟺synΓ(𝑒)=𝑆forsome𝑆≤𝐴. Thus declarative typechecking is decidable. When synthesis succeeds, 𝑆 is the least type, up to =D, among the declarative types of this term with its fixed annotations and fixed context.
Proof. Apply lemma 20.38 for the forward implication. Conversely, lemma 20.37 types 𝑒 at 𝑆. Rule T-Sub then uses 𝑆≤𝐴. The final claim is the quantified leastness conclusion. ◻
The qualification “with fixed annotations” is essential. The procedure checks a written interface; it neither infers one nor proves a principal-type theorem for an unannotated intersection language.
★★★ Prove the application case of the checker characterization in both directions. For completeness, start from a declarative T-App derivation and recursive results 𝐹0≤𝐹 and 𝑆0≤𝑆; derive both algorithmic callability tests and 𝐹0∘𝑆0≤𝐵. For soundness, start from a successful algorithmic application call and reconstruct a declarative T-App conclusion at its returned type. Name every use of arrow variance and lemma 9.23.
Let 𝑧:𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅. The term 𝖼𝖺𝗌𝖾𝖳𝗒𝗉𝖾𝑧𝖺𝗌𝑥𝗂𝗇𝖭𝖺𝗍⇒𝑥∣𝑥 has type 𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅. In the then branch, 𝑥:(𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅)∧𝖭𝖺𝗍=D𝖭𝖺𝗍; in the else branch, 𝑥:(𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅)∧¬𝖭𝖺𝗍=D𝖡𝗈𝗈𝗅. Here is the complete derivation. Put 𝑆=𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅. The two subtype equalities above give 𝑥:𝑆∧𝖭𝖺𝗍∈𝑥:𝑆∧𝖭𝖺𝗍𝑥:𝑆∧𝖭𝖺𝗍⊢𝑥:𝑆∧𝖭𝖺𝗍T−Var𝑆∧𝖭𝖺𝗍≤𝖭𝖺𝗍𝑥:𝑆∧𝖭𝖺𝗍⊢𝑥:𝖭𝖺𝗍T−Sub.𝑥:𝑆∧¬𝖭𝖺𝗍∈𝑥:𝑆∧¬𝖭𝖺𝗍𝑥:𝑆∧¬𝖭𝖺𝗍⊢𝑥:𝑆∧¬𝖭𝖺𝗍T−Var𝑆∧¬𝖭𝖺𝗍≤𝖡𝗈𝗈𝗅𝑥:𝑆∧¬𝖭𝖺𝗍⊢𝑥:𝖡𝗈𝗈𝗅T−Sub. Let D+ be the T-Sub derivation of 𝑥:𝑆∧𝖭𝖺𝗍⊢𝑥:𝖭𝖺𝗍, and let D− be the T-Sub derivation of 𝑥:𝑆∧¬𝖭𝖺𝗍⊢𝑥:𝖡𝗈𝗈𝗅. Both refinements are nonempty, so the empty-branch implications are vacuous and the remaining instance is 𝑧:𝑆∈𝑧:𝑆𝑧:𝑆⊢𝑧:𝑆T−Var𝑥≠𝑧fv(𝑥)⊆{𝑧,𝑥}D+D−𝑧:𝑆⊢𝖼𝖺𝗌𝖾𝖳𝗒𝗉𝖾𝑧𝖺𝗌𝑥𝗂𝗇𝖭𝖺𝗍⇒𝑥∣𝑥:𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅T−Case.
This is occurrence typing for one evaluated value named by a binder. General occurrence systems also refine repeated expressions, projections, and paths, and must prove that evaluation does not invalidate those refinements. No such claim is made here.
Put 𝑊=𝖭𝖺𝗍∨𝖡𝗈𝗈𝗅 and give 𝑧 the deliberately overlapping presentation 𝖭𝖺𝗍∨𝑊=D𝑊. Testing 𝑊 makes the else refinement empty, not the other written arm 𝖭𝖺𝗍. Conversely, testing 𝖭𝖺𝗍 gives the else type 𝑊∧¬𝖭𝖺𝗍=D𝖡𝗈𝗈𝗅, a proper subtype of the other written arm 𝑊. Replacing an else refinement by “the other union arm” is therefore unsound in the first order and imprecise in the second.
For array access, both (𝑎,𝑖)=([10,20],1)and(𝑎′,𝑖′)=([10,20],7) have the same unary types 𝑎,𝑎′:𝖠𝗋𝗋𝖺𝗒𝖭𝖺𝗍 and 𝑖,𝑖′:𝖭𝖺𝗍. Only the first array access satisfies 0≤𝑖<𝗅𝖾𝗇(𝑎). Unary Boolean combinations cannot express a constraint relating an array value 𝑎, an index 𝑖, and 𝗅𝖾𝗇(𝑎). Such a constraint requires dependent refinements, not another semantic-subtyping connective.
Results and signature boundaries
For 𝜆𝖥𝖦 as defined in definition 9.4, definition 9.18, definition 9.19, definition 9.20 the development establishes Boolean semantic subtyping, a terminating and complete subtype decision procedure including arrows and negation, decidable checking of annotated terms, preservation, progress, and safety. The characteristic result is theorem 9.35: synthesis returns a least type for a term with fixed annotations and context.
The signatures separate the following constructions:
𝐴∧𝐵 and 𝐴∨𝐵 classify one value by Boolean operations; 𝐴×𝐵 classifies a pair and 𝐴+𝐵 a tagged value.
The arrow laws (9.4) and (9.5) are inclusions; their reverse directions would require graph-membership conditions absent from the hypotheses.
The checker decides a term with a written interface. Principal inference would also have to construct that interface.
The safety theorem uses the weak call-by-value contexts of definition 9.20; call by name, strong reduction, nondeterminism, recursion, and effects define different step relations.
The typecase rule refines its bound variable by 𝑆∧𝑈 or 𝑆∧¬𝑈. It introduces no path predicate for an arbitrary subexpression.
The finite-graph interpretation maps types to subsets of 𝐷. Term typing and reduction remain syntactic, so no denotational adequacy claim for program phrases enters the safety proof.
Dependent and non-idempotent intersections have different formation and elimination rules from the idempotent semantic intersection used here.
Sources.
The finite-graph model, Boolean normalization, and decomposition method follow Frisch, Castagna, and Benzaken [FCB08]; the chapter specializes their regular setting to finite type trees. For the binder/typecase boundary, see Castagna et al. [CLNL22]. The optional non-idempotent comparison follows Bernadet and Graham-Lengrand [BGL13].
Suggested first pass.
None of these problems is a prerequisite for later chapters. Begin with exercise 9.16; it reconstructs the chapter’s principal binder-refinement mechanism. Then use exercise 9.17 to check the exact handoff to refinements.
★★☆ Repeat the complete occurrence derivation with the test 𝖡𝗈𝗈𝗅. State both semantic subtype equalities and the order of the two branch types in the concluding union.
★☆☆ Give two further same-typed array/index pairs, one satisfying (9.17) and one violating it. Explain why adding more unions and intersections of 𝖠𝗋𝗋𝖺𝗒𝖭𝖺𝗍 and 𝖭𝖺𝗍 cannot distinguish them.
★★★Practical project.semantic-subtyping-counterexample Build and run a finite-graph inclusion checker. Maintain the invariant that every negative inclusion result carries a graph admitted by the left normal form and excluded by the right. The eight-case run must end with All 8 semantic-subtyping corpus cases passed., and the audit must be empty. Test three deliberately unsound variants: remove the Ω guard, change universal arrow decomposition to existential choice, and bypass a typecase scope check. The named eight cases must reject each variant. Passing these finite witnesses is not a proof of the simulation or safety theorems.
The semantic-subtyping literature writes 𝐴≃𝐵 for equality of denotations. This book reserves ≃ for equivalence of types in the homotopy-theoretic sense, where the coherence data is part of the definition, and writes =D here. The relation is unchanged; only the glyph differs.↩︎