Lectures onType Theory
Chapter 106
Chapter 106Optional

Dependent Subtyping, Refinement, and Graduality

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

Suppose a function accepts every nonzero integer and returns a vector whose length is the absolute value of its argument. A client promises a positive integer and needs only a nonempty vector. Ordinary arrow variance compares the two domains and the two codomains independently. It cannot express the second comparison, because the codomains mention the argument: (x:NonZero)VecA(|x|),(x:Positive){v:VecA(|x|)0<length(v)}. The codomain comparison must be made after the client domain has replaced the provider domain. Refinement checking adds a logical entailment to that comparison. Gradual typing instead inserts a run-time cast. These are three different mathematical operations; the rules below never exchange their metatheorems.

The dependent-subtyping ledger

Definition 106.1 — The system λ P_≤

Kinds, types, and terms are generated by K::=UΠx:AK,A,B::=αΠx:ABλx:A.BAM,M,N::=xλx:A.MMN. A context contains term declarations x:A, kind declarations α:K, and bounded type declarations αA:K. The four judgments are context formation Γctx, kinding ΓA:K, typing ΓM:A, and declarative subtyping ΓA<:B. The symbol <: has the declarative role fixed in chapter 8; it does not denote logical implication or gradual precision.

The rules needed for dependent preconditions and postconditions are

ΓA:UΓ,x:AB:U
ΓΠx:AB:U
Π-F
Γ,x:AM:B
Γλx:A.M:Πx:AB
Π-I
ΓF:Πx:ABΓN:A
ΓFN:B[N/x]
Π-E
ΓA2<:A1Γ,x:A2B1<:B2
ΓΠx:A1B1<:Πx:A2B2
Π-Sub

The last rule strengthens the client’s precondition from A1 to A2 and weakens the provider’s postcondition from B1 to B2 in the context where x:A2. Reversing the first premise would let a client pass an argument outside the provider’s domain.

Let P<:N abbreviate the established subtype Positive<:NonZero. Assume that in x:P one has VecA(|x|)<:{v:VecA(|x|)0<length(v)}. One application of Π-Sub derives the client-facing type Πx:NVecA(|x|)<:Πx:P{v:VecA(|x|)0<length(v)}. The occurrence of x in both codomains is checked under x:P; no capture-avoiding renaming or coercion of indices is implicit in the display.

Lemma 106.2 — Dependent application through subtyping

Let ΓF:Πx:A1B1, ΓN:A2, ΓA2<:A1, and Γ,x:A2B1<:B2. Then ΓFN:B2[N/x].

Proof of Lemma 106.2 — Dependent application through subtyping

Proof. By Π-Sub and subsumption, ΓF:Πx:A2B2. Rule Π-E then gives ΓFN:B2[N/x]. The same substitution [N/x] acts on the codomain used in the subtyping premise and on the application result, so the result contains no untransported occurrence of x. ◻

Exercise 106.1

★★☆ Let P<:N<:I. For families Q0,Q1,Q2 assume x:PQ0(x)<:Q1(x)<:Q2(x). Derive (x:I)Q0(x)<:(x:P)Q2(x). Write both applications of Π-Sub and the transitivity step. Then reverse only the domain premise and give a client argument showing why the resulting rule is unsafe.

The difficult metatheory is not hidden in the four rules. Conversion and transitivity prevent direct inversion of a derivation of Πx:AB<:Πx:AB. The source algorithm repairs this by splitting beta reduction: β2 exposes the head constructor used by algorithmic subtyping, while β1 handles the remaining conversions.

Theorem 106.3 — λ P_≤ metatheory

For the exact Church-style signature of definition 106.1, the following hold.

  1. If ΓA0<:A, replacing x:A by x:A0 in a derivable suffix preserves every judgment in that suffix.

  2. Capture-avoiding substitution preserves kinding, typing, and subtyping.

  3. If ΓJ and J contracts by one β1- or β2-step to J, then ΓJ.

  4. Algorithmic subtyping on β2-normal, well-kinded types is sound and complete for declarative subtyping. Formation, kind inference, minimal type inference, and subtyping are decidable on well-formed inputs.

Proof of Theorem 106.3 — λ P_≤ metatheory

Proof. Prove clauses 1–3 simultaneously by induction on derivations. For narrowing, the variable equal to x is retyped by the premise A0<:A and subsumption; every other variable is unchanged. Under a term or type binder, alpha-rename the binder outside FV(A0)dom(Γ) and apply the induction hypothesis to the suffix. Dependent-product subtyping uses the induction hypothesis contravariantly in its domain and under the narrowed client domain in its codomain. Bound selection uses transitivity with the narrowed bound. These are the variable, binder, product, bound, and structural rule families.

For substitution, the variable equal to the substituted variable uses the substituting typing derivation; a different variable is unchanged. Type and term application use both induction hypotheses. Under each dependent binder, choose a name outside the free variables of the substituting expression and apply the induction hypothesis to the renamed body. Kinding and subtyping rebuild their product and bound rules after the same capture-avoiding substitution. Thus substitution preserves all three judgments. A β1 or β2 root is then an instance of substitution; congruence cases use the induction hypothesis under the unique reduction context, and conversion cases use transitivity. This proves clause 3.

For clause 4, first β2-normalize both well-kinded input types. The algorithm compares equal head variables, decomposes dependent products contravariantly in the domain and covariantly in the codomain, and replaces a bounded variable by its declared upper bound only in the designated bound rule. Its recursive measure is the lexicographic pair consisting of the number of unreduced β2 roots and the sum of the two normal-form sizes; following a declared bound decreases the derivation height of the input’s kinding proof. Hence every recursive call terminates on well-formed inputs.

Soundness is induction on the algorithmic derivation: reflexivity, product, and bound calls rebuild the corresponding declarative rules, while the two normalization phases use clause 3 and conversion. For completeness, induct on a declarative subtyping derivation after eliminating transitivity: commute a transitivity conclusion upward until either its middle type is a head constructor, where the two neighboring rules compose componentwise, or a bounded variable, where the bound rule absorbs it. The measure is the number of transitivity rules below constructor rules, followed by total derivation height. The resulting syntax-directed derivation is exactly an algorithmic one. Formation and kind inference recurse on syntax; minimal typing recurses on the Church annotations; subtyping uses the terminating procedure just proved. Equality of names and the grade-free syntax are decidable, so the four judgments are decidable on well-formed inputs. ◻

Dropping well-formedness from clause 4 invalidates the termination argument: the algorithm removes kinding premises from recursive subtyping calls and relies on an outer proof that the two inputs have kinds. Feeding an arbitrary raw type is therefore outside the decision theorem rather than a negative answer returned by it.

The refinement ledger

Dependent subtyping compares types by rules internal to λP. An SMT-backed refinement checker instead discharges a first-order implication. Fix the difference-logic fragment and its certificate checker from chapter 10. The following calculus, DRef, makes the dependency boundary explicit.

Definition 106.4 — Dependent difference refinements

Base shapes are Int and Arr. Refinement types and dependent function types are R,S::={ν:Bϕ}Πx:RS, where ϕ is a finite conjunction of difference constraints r1r2k. A vertex r is 0, an in-scope integer variable, or len(a) for an in-scope array variable a. In a refinement of Int, the distinguished vertex ν denotes the refined integer; in a refinement of Arr, len(ν) denotes the refined array’s length. Every other free vertex of ϕ must be declared earlier in the context. The bare shape B abbreviates {ν:B}.

For integers m,miZ, terms, values, and A-normal call-by-value evaluation contexts are e::=vev,v::=xmm1,,mkλx:R.e,E::=[]Ev. The root and compatible reduction rules are (λx:R.e)ve[v/x]eeE[e]E[e]. For a base value v, the notation ϕ[v/ν] replaces ν by an integer variable or literal, or replaces len(ν) by an array variable’s length or an array literal’s length. For later synthesis, write [m]Int:={ν:Intν0m0νm},[m1,,mk]Arr:={ν:Arrlen(ν)0k0len(ν)k}. These singleton refinements record the integer itself or the array length; both are expressible as two difference constraints.

The three judgments of the refinement ledger are well-formedness ΓDRefRtype, typing ΓDRefe:R, and refinement subtyping ΓDRefR<:S. The macro <: denotes this logical-implication role, not λP subtyping.

Write Φ(Γ) for the conjunction of the base-refinement assumptions in Γ: a declaration x:{ν:Bθ} contributes θ[x/ν], while a dependent-function declaration contributes no difference constraint. The core rules are

fv(ϕ)dom(Γ){ν}Γvertices(ϕ)well-sorted
ΓDRef{ν:Bϕ}type
R-Base-F
ΓDRefRtypeΓ,x:RDRefStype
ΓDRefΠx:RStype
R-Π-F
Entails(Φ(Γ)ϕ1,ϕ2)
ΓDRef{ν:Bϕ1}<:{ν:Bϕ2}
R-Base-Sub
ΓDRefR2<:R1Γ,x:R2DRefS1<:S2
ΓDRefΠx:R1S1<:Πx:R2S2
R-Π-Sub

Here Entails(Ψ,ϕ) is semantic entailment of the difference constraint ϕ by Ψ. The checker does not trust an SMT solver’s Boolean answer: each requested atomic consequence is accompanied by a shortest-path certificate, and the small checker recomputes the path weight. If the antecedent is inconsistent, the certificate is instead a negative cycle whose edge weights sum to a negative integer.

Type equality in DRef is alpha-equivalence for binders together with mutual certified implication for base refinements. Thus predicates with different syntax may define equal types, but neither proof irrelevance nor erasure turns an implication in one direction into equality.

The introduction, elimination, and subsumption rules are

Γ(x)=R
ΓDRefx:R
R-Var
ΓDRef{ν:Intϕ}typeEntails(Φ(Γ),ϕ[m/ν])
ΓDRefm:{ν:Intϕ}
R-Int
ΓDRef{ν:Arrϕ}typeEntails(Φ(Γ),ϕ[m1,,mk/ν])
ΓDRefm1,,mk:{ν:Arrϕ}
R-Arr
Γ,x:RDRefe:S
ΓDRefλx:R.e:Πx:RS
R-Lam
ΓDRefe:Πx:RSΓDRefv:R
ΓDRefev:S[v/x]
R-App
ΓDRefe:RΓDRefR<:S
ΓDRefe:S
R-Sub

A neutral application fv is stuck when f is a variable; the typing judgment does not invent a lambda body.

The term rule R-Sub makes direct recursion on a declarative derivation nonalgorithmic: a checker would have to guess the type before its final subsumption. Principal synthesis removes that guess.

Definition 106.5 — Principal synthesis and checking

Write ΓDRefeR when e synthesizes R, and ΓDRefeR when e checks against R. The rules are

Γ(x)=R
ΓDRefxR
A-Var
ΓDRefm[m]Int
A-Int
ΓDRefm1,,mk[m1,,mk]Arr
A-Arr
ΓDRefRtypeΓ,x:RDRefeS
ΓDRefλx:R.eΠx:RS
A-Lam
ΓDRefeΠx:RSΓDRefvR
ΓDRefevS[v/x]
A-App
ΓDRefeRΓDRefR<:S
ΓDRefeS
A-Check

Algorithmic subtyping is the structural recursion given by R-Base-Sub and R-Π-Sub; it contains no term subsumption rule. The base case invokes the certified difference-logic decision described after definition 106.4. Thus synthesis chooses a unique outer constructor, and checking performs one final subtype test rather than searching for uses of R-Sub.

Lemma 106.6 — Logical substitution

Suppose the declaration of x contributes the well-sorted assumption ϕx to Φ(Γ,x:R). Let v be an integer variable or literal, or an array variable or literal, of the same base shape in Γ. If Entails(Φ(Γ)ϕx,ψ)andEntails(Φ(Γ),ϕx[v/x]), then Entails(Φ(Γ),ψ[v/x]).

Proof of Lemma 106.6 — Logical substitution

Proof. Let ρ be a valuation satisfying Φ(Γ). Extend ρ by mapping x to the integer denoted by v, or by mapping len(x) to the length denoted by the array value v. Variables are interpreted by ρ; literals have their displayed integer or length. The second hypothesis gives ϕx[v/x] under ρ, so the extended valuation satisfies Φ(Γ),ϕx. The first hypothesis then gives ψ. Evaluating ψ in the extension is the same integer calculation as evaluating ψ[v/x] under ρ. Since ρ was arbitrary, the required entailment holds. ◻

Lemma 106.7 — Refinement narrowing and substitution

The following statements hold in DRef.

  1. If ΓDRefR<:R and Γ,x:R,ΔDRefJ, then Γ,x:R,ΔDRefJ.

  2. If Γ,x:R,ΔDRefJ and ΓDRefv:R, then Γ,Δ[v/x]DRefJ[v/x].

The metavariable J ranges over type formation, typing, and subtyping judgments.

Proof of Lemma 106.7 — Refinement narrowing and substitution

Proof. For narrowing, induct on the derivation of J. Variable typing uses reflexivity when the selected declaration is not x and uses subsumption from R to R when it is x. In R-Base-Sub, the assumptions contributed by R imply those contributed by R, so composing implications preserves the entailment premise. The binder cases rename their bound variable to a name outside dom(Γ,Δ){x} and apply the induction hypothesis under the extended context. Formation, application, and subsumption rebuild their displayed rules. These are all rule families.

For substitution, use simultaneous induction on the three derivations. The variable case for x is the given derivation of v:R; every other variable case is unchanged. Rule R-Base-Sub uses lemma 106.6 when R is a base refinement. The value grammar and inversion of its typing derivation make v an integer or array variable or literal in that case. When R is a dependent function type, well-sortedness forbids x as a difference-logic vertex, so the entailment is unchanged. In R-Lam and R-Π-F, alpha-rename the binder y so that yfv(v)dom(Γ,Δ){x}, then apply the induction hypothesis to the body. Rule R-App applies the two induction hypotheses and uses S[u/y][v/x]=S[v/x][u[v/x]/y], whose freshness premise is the chosen yfv(v). Subsumption applies both induction hypotheses and rebuilds R-Sub. Base formation performs literal normalization of difference constraints after substitution. No other rule binds a variable or changes a predicate. ◻

Lemma 106.8 — Certified subtyping structure

For well-formed DRef types, certified subtyping is reflexive and transitive. A derivation relates only two base refinements of the same shape or two dependent function types. In particular, ΓDRefΠx:R1S1<:Πx:R2S2 has premises ΓDRefR2<:R1 and Γ,x:R2DRefS1<:S2.

Proof of Lemma 106.8 — Certified subtyping structure

Proof. Outer-form inversion follows because R-Base-Sub and R-Π-Sub are the only subtyping rules. Reflexivity is structural induction on the type. At a base type it is reflexivity of semantic implication. At a dependent function, apply the induction hypotheses to the domain and to the codomain under its binder, then apply R-Π-Sub.

For transitivity, induct on the middle type. At a base type, implication composition gives the required Entails premise. For dependent functions, suppose the two derivations have respective codomain premises Γ,x:R2DRefS1<:S2,Γ,x:R3DRefS2<:S3 and domain premises R2<:R1 and R3<:R2. The domain induction hypothesis gives R3<:R1. Narrow the first codomain premise from x:R2 to x:R3 using lemma 106.7; the codomain induction hypothesis then gives S1<:S3 under x:R3. Rule R-Π-Sub completes the derivation. ◻

Theorem 106.9 — Correctness and completeness of principal checking

Let Γ be well formed and let every lambda domain in e be well formed. Then:

  1. if ΓDRefeP, then ΓDRefe:P;

  2. if ΓDRefe:R, then synthesis derives a unique P such that ΓDRefeP and ΓDRefP<:R;

  3. ΓDRefeR if and only if ΓDRefe:R.

Proof of Theorem 106.9 — Correctness and completeness of principal checking

Proof. For clause 1, use simultaneous induction on synthesis and checking, with the auxiliary claim that ΓDRefeR implies ΓDRefe:R. The variable and lambda cases apply R-Var and R-Lam. The exact singleton constraints of A-Int and A-Arr hold after substituting the displayed literal, so R-Int and R-Arr apply. The application case uses the synthesis and checking induction hypotheses before applying R-App. In the auxiliary A-Check case, the synthesis induction hypothesis followed by R-Sub proves the claim.

For clause 2, induct on the declarative typing derivation. Variables synthesize their declarations. In the integer case, any valuation satisfying Φ(Γ) and ν=m satisfies the requested predicate because the premise of R-Int proves that predicate after substituting m for ν. Hence [m]Int is a subtype of the requested refinement. The array case uses the same valuation argument with len(ν)=k. In the lambda case, the induction hypothesis for the body gives P<:S; reflexivity on the annotated domain and R-Π-Sub give Πx:RP<:Πx:RS.

In the application case, let the induction hypothesis for the function give ΓDRefeΠx:R0S0,ΓDRefΠx:R0S0<:Πx:RS. By lemma 106.8, R<:R0 and S0<:S under x:R. If Pv is the synthesized type of v, the value induction hypothesis gives Pv<:R; transitivity gives Pv<:R0, so A-Check checks v against R0. Rule A-App synthesizes S0[v/x]. Declarative typing gives v:R by clause 1 and subsumption, so substitution in lemma 106.7 gives ΓDRefS0[v/x]<:S[v/x]. Finally, a declarative R-Sub case composes the subtype supplied by the induction hypothesis with its displayed subtype premise. These are all declarative typing rules.

Each synthesis rule is selected by the outer term constructor, and A-App recurses on the proper function subterm. Thus the synthesized type is unique. Clause 3 follows from clauses 1 and 2 together with A-Check. ◻

Theorem 106.10 — Preservation and decidability for DRef

If DRefe:R and ee, then DRefe:R. For well-formed contexts and fully annotated terms, type checking and subtyping in DRef are decidable.

Proof of Theorem 106.10 — Preservation and decidability for DRef

Proof. For preservation, induct on the reduction derivation. Consider first the root beta step (λx:R0.e0)ve0[v/x] at a declared result type T. By theorem 106.9, its unique synthesis derivation ends in A-App and has the form x:R0DRefe0S0DRefλx:R0.e0Πx:R0S0DRefvR0DRef(λx:R0.e0)vS0[v/x], together with S0[v/x]<:T. Soundness of synthesis and checking gives x:R0DRefe0:S0 and DRefv:R0. Substitution gives DRefe0[v/x]:S0[v/x]; one use of R-Sub at S0[v/x]<:T restores the declared result type. Thus no inversion through a hidden use of R-Sub is required.

For a compatible step e0v1e0v1, principality gives a synthesized function type Πx:R1S1, a check of v1 against R1, and a final relation S1[v1/x]<:T. The induction hypothesis preserves e0:Πx:R1S1. Rule R-App, followed by the recorded final subtyping relation, types e0v1:T. These are all reduction rules.

For decidability, execute the rules of definition 106.5. Synthesis recurses on a proper term subexpression; checking makes one structural subtyping call. Function subtyping recurses on strict type subexpressions. A base call asks finitely many difference-constraint consequences. For an antecedent graph G, a consequence holds when either G has a negative cycle, making the antecedent inconsistent, or G has no negative cycle and its shortest-path bound implies the requested inequality. Bellman–Ford terminates on the finite vertex set; the certificate checker validates the returned cycle in the first case and the returned path bound in the second. Alpha-equivalence and well-formedness are structural decisions. The equivalence in theorem 106.9 transfers this decision from algorithmic checking to declarative typing with R-Sub. ◻

A difference constraint r1r2k contributes the directed edge r2kr1. A path certificate records a vertex sequence whose edges occur in the antecedent graph; its recomputed weight must be at most the goal bound. A negative-cycle certificate records r0,,rn with rn=r0, checks every edge against the graph, and requires the recomputed sum to be negative.

For a concrete inconsistent antecedent, take x00,0x1. Its graph contains 00x10. The displayed two-edge cycle has total weight 1, so the certificate checker accepts it. The antecedent asserts both x0 and 1x; hence R-Base-Sub may derive any requested base refinement from it. This branch is a decision, not a successful shortest-path proof: it records that the context itself is inconsistent.

The well-formedness restriction matters. If a predicate mentions an undeclared array a, the vertex len(a) has no interpretation in a valuation of Γ. Treating the missing vertex as zero would make the checker prove a different formula.

Exercise 106.2

★★☆ Let R1={ν:Int0ν} and R2={ν:Int1ν}. Derive R2<:R1. Under x:R1, type a function whose result has refinement 0νx. Narrow the context to x:R2 and list the graph edges used by the new entailment. Finally remove the premise R2<:R1 and give the valuation x=1 that invalidates the claimed narrowing step.

The following calculation isolates the refinement-ledger obligation in a familiar bounds-checked client. Suppose a host language has integer comparison, conditionals, and an array-selection constant with interface get:Πa:ArrΠi:{ν:Int0ν<len(a)}Int. Suppose its then branch contributes the guard as a logical assumption. The host program is λa:Arr.λi:{ν:Int0ν}.if i<len(a) then getai else 0. The DRef-owned calculation begins only after entering the then branch. Its graph has the parameter edge i00, representing 0i0, and the guard edge len(a)1i, representing ilen(a)1. The second edge is itself a certificate for the strict upper bound required by get; the first certifies the lower bound. The else branch contains no array selection and requests no bounds certificate.

This paragraph proves only those two difference-logic consequences. The conditional, comparison, and selection constructs are outside the term grammar of definition 106.4, so it is not a typing or preservation derivation for an unprinted extension of DRef. Nor does it assert which solver, erasure policy, or operational equations are implemented by ATS, Liquid Haskell, or another host language.

The gradual-dependent ledger

Replacing a missing proof by an erased refinement assumption would make the preceding program trust the assertion. Gradual CIC takes another route: a gain of precision becomes an explicit computation that may produce an error.

Definition 106.11 — GCIC cast interface

The source contains universe-indexed unknown terms ?A and errors errA. When a term t known at A is checked at a consistent type B, bidirectional elaboration inserts cast[BA](t). The target is CastCIC. A downcast inspects the value’s constructor or universe tag; a failed inspection reduces to errB.

Write PrecΓ(t,u) for the source’s well-typed precision proposition. This notation is chapter-local prose notation, not the nondependent precision relation of chapter 11. The selected variant below is GCICG: it is conservative over CIC and satisfies graduality, but it is not normalizing.

For a static natural 4, the round trip cast[N?](cast[?N](4))4 is an embedding followed by its projection. Replacing the inner value by a Boolean reaches errN. These reductions are not refinement subtyping derivations: the cast remains at run time and can fail.

Definition 106.12 — Context-wise reduction retraction

For a closed term e, put Stepsk(e):=e0,,ek.e=e00i<keiei+1. A gradual theory has context-wise reduction retraction when the following holds. Let A be more precise than B, let t:A, and let C[] be any well-typed one-hole term context whose hole has type A. For every k:Nat, (CR)Stepsk(C[t])Stepsk(C[cast[AB](cast[BA](t))]). Thus the round trip may delay the surrounding computation, but it cannot remove a finite reduction prefix obtained from t. This property is stronger than observational equiprecision, which does not compare reduction lengths.

Theorem 106.13 — Fire triangle for gradual CIC

Assume a gradual dependent theory satisfies the following three properties.

  1. It is conservative over CIC, including the simply typed fragment in one universe with the same beta-reduction step.

  2. It has a universal unknown type ?, and ?? is more precise than ?.

  3. It satisfies context-wise reduction retraction (CR) of definition 106.12.

Then the theory is not strongly normalizing.

Proof of Theorem 106.13 — Fire triangle for gradual CIC

Proof. Let δ=λx:?.cast[???](x)x,Ω=δcast[???](δ). Put U=??, u=cast[?U](δ), and C[z]=zu. Clauses 1 and 2 type δ:U, u:?, and Ω=C[δ]:?.

We prove Stepsk(Ω) by induction on k:Nat. The empty sequence proves the case k=0. Suppose Stepsk(Ω). Since Ω=C[δ], clause 3 with A=U and B=? gives (1)Stepsk(C[cast[U?](cast[?U](δ))]). One beta step gives (2)ΩC[cast[U?](cast[?U](δ))]. Prefix the k steps from (1) by (2). This proves Stepsk+1(Ω).

Thus Ω has a reduction prefix of every finite length and cannot be strongly normalizing. ◻

The proof uses the three hypotheses at different points. Conservativity types the simply typed arrow skeleton of δ and Ω. Universality makes the self-applications typable and gives the precision comparison from U to ?. Context-wise reduction retraction preserves the induction hypothesis through the cast round trip. Ordinary embedding–projection equiprecision does not give that finite-step conclusion. Removing any one of the three hypotheses blocks this construction, but this observation is not a countermodel proving logical necessity, and no converse is claimed.

Theorem 106.14 — GCIC_G guarantee

For the CastCICG syntax, typing, reduction, and semantic precision fixed in definition 106.11, the following hold.

  1. Cast insertion preserves typing and CastCICG has progress and preservation with errors counted as outcomes.

  2. Static CIC terms elaborate conservatively: erasing their inserted casts recovers the CIC term and type.

  3. If PrecΓ(t,u), then every closing Boolean observation of t is an error-or-divergence refinement of the corresponding observation of u.

  4. If A is more precise than B, the upcast from A to B and the downcast from B to A form an embedding–projection pair; the downcast after the upcast is equiprecise with the identity on A.

No normalization conclusion is included.

Proof of Theorem 106.14 — GCIC_G guarantee

Proof. For clause 1, induct simultaneously on elaboration and target typing. Variables and static constructors elaborate homomorphically. A consistency check between A and B inserts cast[BA]; the cast typing rule has exactly the two formation premises produced by the induction hypotheses. Dependent application substitutes the elaborated argument into both the source and target codomain. Inductive elimination substitutes the constructor indices into its motive. These are the binder, conversion, application, constructor, and eliminator families, so cast insertion preserves typing.

Preservation is induction on a CastCICG root step. A successful cast between equal head constructors recursively casts their parameters and indices, and the constructor typing rule rebuilds the result. A failed head comparison yields errB:B. Beta, iota, and fixpoint roots use substitution; congruence uses the induction hypothesis. For progress, invert a closed typing derivation. A lambda or constructor is a value; an error is an allowed outcome; application, elimination, and cast forms either contain a reducible subterm or match one of the preceding roots. This proves the target part of clause 1.

For clause 2, induct on a static CIC elaboration. No unknown or error rule can be the last rule. Every inserted cast therefore has equal source and target types and erases to the identity. The binder and inductive cases commute with erasure and substitution, so erasing all inserted casts recovers the original term and type.

For clauses 3–4, interpret every type by a pointed omega-cpo of computations and define an admissible precision relation on that domain. At a universe or inductive type, the relation compares equal head constructors componentwise; on the less precise side it also admits the error point and the least element representing divergence. At a dependent product it relates functions that send related arguments to related results. At an inductive family it also requires the constructor indices to be related. Admissibility closes each clause under limits of increasing computation chains, so a diverging approximation cannot be mistaken for a terminating constructor.

The fundamental lemma is a simultaneous induction on the precision and typing derivations, strengthened to related substitutions. Variables use the substitution relation. Constructors and eliminators use the corresponding domain clauses. Dependent binders apply the induction hypothesis after extending both substitutions by related arguments. The cast case uses the constructor-directed reduction from clause 1; incompatible heads land at the error point, while compatible heads reduce to the component relations. Conversion uses invariance of the interpretation under definitional equality. These cases exhaust the static, binder, inductive, conversion, and cast rule families. Specializing the fundamental lemma to closing Boolean contexts gives exactly the observation refinement of clause 3: a Boolean constructor on the precise side is matched by the same constructor, an error, or divergence on the less precise side.

If A is more precise than B, the upcast maps each related A-value to its B image. The downcast performs the same constructor test in reverse. The type induction shows that downcast after upcast returns the original constructor and recursively satisfies the relation on every field; functions use extensionality at related arguments. Hence the round trip is equiprecise with the identity on A, proving clause 4. This observational result does not compare finite reduction lengths, so theorem 106.13 still rules out adding strong normalization under context-wise reduction retraction. ◻

Indexed inductives expose the run-time obligation. For vectors, the selected CastCIC extension contains constructor-directed roots including cast[VecB0VecA0](nilA)nilB,cast[VecB0VecA(sucn)](consAanv)errVecB0. The constructor and index are checked together. The source calculates this vector extension and conjectures a generalization only for inductive families with concretely forceable indices; no theorem here promotes the vector roots to an arbitrary indexed-inductive schema.

Exercise 106.3

★★☆ Calculate the two reductions obtained by first casting nilA and consAa0(nilA) to an unknown vector index and then downcasting to index 0. State which constructor test fails. Explain why the successful reduction is an embedding–projection calculation and not proof irrelevance.

An interoperability boundary

Chapter 11 cards a boundary calculus in which a typed and an untyped side exchange values through explicit checks. Return to it with an index-refining client. A list/vector boundary relates two representations; it is neither refinement subtyping nor a GCIC cast. Let forgetn:VecAnListA erase the index, and let checkn:ListAOption(VecAn) compare the list length with n.

Proposition 106.15 — Round trips at the list/vector boundary

For every n and every v:VecAn, checkn(forgetn(v))=some(v), and for every list l, if checkn(l)=some(v) then forgetn(v)=l.

Proof of Proposition 106.15 — Round trips at the list/vector boundary

Proof. Both directions are structural inductions on n. For the first, at n=0 the only vector is nil, forget0 returns the empty list, and check0 accepts it. At sucn write v=consav; forget emits a and recurses, and checksucn strips a and recurses, so the induction hypothesis applies to v and the head a is returned unchanged. The second direction inducts on the same measure and reads the two recursive equations in the other order. Neither direction makes the pair an equivalence, because checkn is partial; exercise 106.7 asks for both inductions in full. ◻

The two round trips are the option-valued shadow of a more structured factorization through the image of forgetn: imforgetn:={l:ListA & v:VecAn. forgetnv=l}, observe that VecAn and imforgetn are equivalent types, and place all the partiality in the remaining leg, which relates imforgetn to ListA and which is a partial connection: a type-theoretic, partial form of a monotone Galois connection. Its two specifications are stated in a monadic order, and the direction from the subset type to the simple type never fails, which is what makes the connection directed. The proposition above is what that factorization yields once the subset type and the equivalence are collapsed into a single Option. The collapse loses the intermediate equivalence needed to lift the boundary to higher-order functions.

Translate a vector client h:VecA(sucn)A to a list boundary by h^n(l)=match checksucn(l) with some(v)some(hv)nonenone. Then h^n(forgetsucn(v))=some(hv) by the first clause of proposition 106.15. A list of length n produces none; this is the boundary’s decidable observation.

The counterexample to identification is a failed length check. In the boundary calculus it returns none and preserves the original list. In CastCIC it is a reduction to a typed error inside the cast calculus. In DRef there is no run-time check at all: an unproved length entailment prevents typing. The three outcomes differ on the same input.

Definition 106.16 — Trust ledger

The chapter’s four trust decisions are as follows.

mechanism checked evidence run-time representation
λP subtyping derivation and conversion no inserted cast
DRef refinement graph certificate refinement erased after checking
CastCICG type-directed cast tag, error, and possible divergence
list/vector connection length decision option success or failure

Proof irrelevance may identify two proofs after typing; it does not discharge an absent entailment. An inconsistent logical assumption can derive every refinement consequence and is therefore part of the trusted input. It cannot be reclassified as a run-time cast failure.

Suggested first pass.

None of these problems is a prerequisite for a later chapter. Begin with exercise 106.4, then complete exercise 106.8.

Exercise 106.4

★☆☆ Reconstruct the derivation in lemma 106.2. Mark the context in which the codomain subtyping premise is checked and the point at which [N/x] is performed.

Exercise 106.5

★★☆ Give two well-formed dependent products for which domain contravariance holds but the codomain premise of Π-Sub fails. Prove failure by a two-element interpretation of the codomain family.

Exercise 106.6

★★☆ For the array client in section 106.2, write the weighted graph in the then branch and a shortest-path certificate for ilen(a)1. Delete the branch assumption and give a valuation refuting the goal.

Exercise 106.7

★★★ Prove both partial-connection laws for forgetn and checkn by induction on n. The inductive step must state the head equality and the recursive tail equation separately.

Exercise 106.8

★★★ Practical project.dependent-boundary-ledger Implement in Kappa a finite checker with three tagged requests: dependent-function variance, difference-constraint entailment with a supplied path certificate, and vector-index casts. The invariant is that a request is processed only by its tag’s ledger. The program must print the accepted positive/nonzero function comparison, accept the certificate for 0i<3, reject the same index claim at i=3, accept the displayed two-edge negative-cycle certificate as an inconsistent antecedent, reduce the nil round trip to nil, and reduce a cons-to-zero cast to error. Require also the named rejections reversed function domain rejected, nonnegative cycle rejected, forged path weight rejected, disconnected certificate rejected, and cross-ledger routing rejected. The acceptance test checks all eleven outcomes. A mutation that routes refinement entailment through the gradual cast handler must fail the cross-ledger oracle. A second well-typed mutation that trusts the advertised path weight instead of summing the named edges must fail the forged-weight oracle. Identify the ledger-isolation invariant broken by the first mutation and the certificate-validation invariant broken by the second.

Sources. Compagnoni and Aspinall give the λP algorithm and metatheory [CA96]. Lennon-Bertrand, Maillard, Tabareau, and Tanter give gradual CIC and its fire triangle [LBMTT22]. Dagand, Tabareau, and Tanter’s printed pp. 7–8 give the list/vector factorization collapsed in proposition 106.15 [DTT18]. Each source proof package is shorter than ten pages and is proved locally.

Search the book

Type to search the local edition.