Lectures onType Theory
Chapter 6
Chapter 6Optional

Dimension Types and Units of Measure

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

Chapter 3 used the discrete base type Nat. To expose the problem, first imagine an unindexed numeric type Num whose values are rational numbers. Write q@u for the literal coefficient q expressed in unit u. With only that unindexed type, both 3@m+2@s and 100@cm+1@m have type Num. The first adds unlike dimensions; the second adds like dimensions written at different scales. Neither distinction is visible to an ordinary numeric type checker. We therefore reuse the syntax and typing discipline of the pure let-language in chapter 3 and add a small algebra of dimensions. The resulting numeric type is indexed: its dimension appears as an argument, as in Num[L]. Inference remains a problem: a programmer may write a generic square function without naming its input dimension, and the algorithm must infer the most general answer.

Dimensions are normalized exponent vectors

Fix a finite set B of base dimensions. In examples we use L for length, T for time, and M for mass. A finite set D of dimension variables is disjoint from B. Each δD is a formal generator that a substitution may later replace by a normalized dimension.

Definition 6.1 — Dimension expression

A normalized dimension expression over a finite variable set D is an exponent map d:BDZ. Since BD is finite, every such map has finite support. For a generator gBD, write eg for the map with exponent 1 at g and 0 elsewhere; in dimension expressions, the same letter g denotes eg. Surface multiplication is pointwise addition of exponent maps, (de)(g)=d(g)+e(g); inversion is pointwise negation, and dn(g)=nd(g). Thus the multiplicative identity 1 is the all-zero map. We use multiplicative notation because it matches dimensional analysis, although the underlying group operation is addition of integer exponents.

Before normalization, surface dimension expressions have grammar d^::=1gd^d^d^n(gBD, nZ). Write d^1 for the power d^1. The normalization map N is defined by N(1)=0,N(g)=eg,N(d^e^)=N(d^)+N(e^),N(d^n)=nN(d^). From here on d,e denote the resulting normalized maps; an instruction to “normalize” a surface expression asks for this map in multiplicative normal form.

When normalized maps d and e have both been formed over the same variable set D, write d=De when their coefficients agree at every generator of BD. Maps formed over different variable sets are first carried to a common variable set by a substitution; they are not compared as written.

Thus LT1T=L,(LT2)2=L2T4, whereas LDT. Equality here is decidable by comparing the finitely many integer coefficients. It says nothing about numerical values.

Let D be another finite set of such variables. A dimension-variable substitution ρ assigns to each δD a normalized map ρ(δ):BDZ. Extend it to base generators by b[ρ]=b and write δ[ρ]=ρ(δ). Its extension to every normalized dimension is d[ρ]=bBbd(b)δDδ[ρ]d(δ). The products are the multiplicative notation for addition of exponent maps. A commutative group on generators G is free abelian when every assignment of the generators to a commutative group H extends to exactly one group homomorphism into H.

Lemma 6.2 — Dimension-group laws

The normalized expressions on BD form a free abelian group. Every dimension-variable substitution is a group homomorphism. In particular, if d=De, then d[ρ]=De[ρ].

Proof of Lemma 6.2 — Dimension-group laws

Proof. Pointwise integer addition is associative and commutative, the zero map is its identity, and d+(d)=0 pointwise for every exponent map d. For the homomorphism law, add the two exponents belonging to each generator: (de)[ρ]=bBbd(b)+e(b)δDδ[ρ]d(δ)+e(δ)=(bBbd(b)δDδ[ρ]d(δ))(bBbe(b)δDδ[ρ]e(δ))=d[ρ]e[ρ]. Negating every exponent in the same formula gives d1[ρ]=d[ρ]1. If d=De, then d(g)=e(g) for every generator g; substituting those equal coefficients in the same formula gives d[ρ]=De[ρ]. For freeness, choose arbitrary images hg of the generators in an abelian group H, and define ϕ(d)=gBDhgd(g). The product is finite because d has finite support. The calculation just used for substitution proves that ϕ is a homomorphism. Every d is the displayed finite product of generator powers; hence any homomorphism with the chosen generator images must have the displayed value ϕ(d). This proves uniqueness. ◻

Exercise 6.1

★☆☆ Normalize (Lδ1)2(δT1)2 and MLT2L1T. State which variables cancel and which base exponents remain.

Definition 6.3 — Units and scales

A unit environment U maps each primitive unit name u to a positive rational scale su and a closed dimension du:BZ, which contains no dimension variables. The scale is measured relative to a chosen canonical unit system: meters for L, seconds for T, and the induced products and powers for compound dimensions. Multiplication by a rational scale keeps every stored coefficient rational. Replacing scales by positive reals changes only the coefficient domain, not the dimension group or its typing theory. For dimensionless angles, choose radians as the canonical unit; degrees and radians then both have dimension 1, while one degree has real scale π/180. If u0 ranges over primitive names, compound units have grammar u::=u0uuu1un(nZ). Their scales and dimensions use suv=susv,duv=dudv,su1=su1,du1=du1,sun=sun,dun=dun. Write U(u)=(su,du) for this recursive extension of U from primitive names to compound unit expressions.

For meters, centimeters, and seconds, take m(1,L),cm(1/100,L),s(1,T). The two length units have equal dimensions and different scales. A meter and a second have different dimensions even though both scales happen to be one. Thus 100@cm+1@m is dimensionally well typed. Its numerical meaning first replaces each coefficient q by its canonical coefficient qsu. The two addends become 1 and 1 at dimension L, so their sum is the canonical value 2.

A pure dimensioned let-language

The source calculus is deliberately small. Its arithmetic exposes the dimension equations; its lambda and let forms expose polymorphic inference.

Definition 6.4 — Types, schemes, and terms

τ::=αNum[d]ττ,σ::=α¯δ¯.τ,e::=xq@uλx.eeelet x=e in e::=e+eeee/een. Here qQ, nZ, and u is a well-formed compound unit expression of definition 6.3. The angle brackets in en mark n as an integer written in the term syntax, not as a source subexpression. Ordinary type variables α,β, and dimension variables δ,ϵ, are disjoint sorts. Formally, if A is a finite set of ordinary variables, formation is generated by

αA
A;Dα type
F-TVar
d is a normalized dimension over D
A;DNum[d] type
F-Num
A;Dτ1 typeA;Dτ2 type
A;Dτ1τ2 type
F-Arrow

A scheme is formed by checking its body after adding its quantified ordinary and dimension variables to the corresponding sets. Fix a total order on variable names; every bar lists its finite set in that order. The displayed sort order has no semantic effect. Thus Num[α] and αδ are not merely discouraged; they are ill sorted. Type substitution preserves these sorts and acts on both kinds of variable.

Instantiation and generalization are those of HM, extended to both sorts of variables. Write fdv for free dimension variables, the dimension-sorted analogue of ftv. List each finite difference below in the fixed total order and set GenΓ(τ)=(ftv(τ)ftv(Γ))(fdv(τ)fdv(Γ)).τ. The term grammar has no references, assignment, or other effects. Therefore the unrestricted HM generalization rule of chapter 3 is sound; the value restriction used for effectful extensions is not needed here.

Definition 6.5 — Dimension typing

Fix the unit environment U throughout this judgment. Use the HM variable, instantiation, lambda, application, generalization, and let rules with the extended type grammar. Numerically, q@u has canonical coefficient qsu; its type records only du, because scale changes a coefficient but never changes whether the literal is dimensionally well formed. The additional arithmetic typing rules are

U(u)=(su,du)
Γq@u:Num[du]
D-Lit
Γe1:Num[d]Γe2:Num[d]
Γe1+e2:Num[d]
D-Add
Γe1:Num[d1]Γe2:Num[d2]
Γe1e2:Num[d1d2]
D-Mul
Γe1:Num[d1]Γe2:Num[d2]
Γe1/e2:Num[d1d21]
D-Div
Γe:Num[d]
Γen:Num[dn]
D-Pow

Extend =D from dimensions to types structurally: a type variable is equivalent only to itself, arrows are compared componentwise, and Num[d]=DNum[e] exactly when d=De. The explicit conversion rule is Γe:ττ=DτΓe:τDConv. Because annotations store normalized maps, any use of D-Conv can be removed: its premise and conclusion types have the same normalized syntax. We retain the rule so metatheoretic derivations can name the equality step explicitly.

Definition 6.6 — Syntax-directed dimension typing

The judgment Γse:τ uses the four syntax-directed HM rules of definition 3.31, generalized over both variable sorts, together with D-Lit, D-Add, D-Mul, D-Div, and D-Pow from definition 6.5. All dimension annotations are stored in normal form, so it has no D-Conv rule.

Lemma 6.7 — Dimension typing is syntax-directed

For a monotype τ, Γe:τΓse:τ. Every syntax-directed derivation has the same subject and type as its declarative image.

Proof of Lemma 6.7 — Dimension typing is syntax-directed

Proof. For the left-to-right direction, induct on the declarative typing derivation. Handle Inst and Gen as in theorem 3.34, first alpha-renaming the quantified ordinary and dimension variables away from every variable already in the derivation. In an arithmetic case, the induction hypotheses give syntax-directed premises at the numeric types shown in that rule; reapply the same arithmetic rule. A final D-Conv disappears because normalized dimensions satisfying d=Dd are the same finite map, and the structural definition of type equivalence never changes an outer constructor. For the right-to-left direction, insert the declarative HM rules and reuse each arithmetic rule unchanged. ◻

Lemma 6.8 — Dimension conversion preserves type shape

If τ=Dτ, then the two types have the same outer constructor. If that constructor is an arrow, their domains and codomains are respectively equivalent; if it is Num, only the dimension annotation may change. In particular, no type variable or arrow is equivalent to a numeric type.

Proof of Lemma 6.8 — Dimension conversion preserves type shape

Proof. Inspect the three defining clauses. Equal variables have the same variable head. For arrows, the definition compares the domains and codomains. For numeric types, it compares only their dimension annotations. No clause relates two different outer constructors. ◻

The declarative rules assign the function square=λx.xx the monotype Num[δ]Num[δ2] under a free generator δD. Generalizing δ gives the scheme δ.Num[δ]Num[δ2]. Instantiating δ=L squares a length; instantiating δ=T1 squares a frequency. By contrast, 3@m+2@s has no derivation because D-Add would require L=DT.

Exercise 6.2

★★☆ Derive the displayed scheme for square. Derive and generalize the type of λx.λy.(xy)/y. Normalize only its dimension: cancelling y changes behavior at y=0, where the original divides by zero.

A short mechanics calculation now checks without a special acceleration primitive. The following display abbreviates the empty-environment monotype derivation followed by generalization: accel=λs.λt.s/(tt):δϵ.Num[δ]Num[ϵ]Num[δϵ2]. At s=100@m and t=10@s, the result has dimension LT2. Trying to add this result to s is rejected.

Solving dimension equations

Ordinary syntactic unification is not enough. The equation δϵ=L has infinitely many solutions and should return one principal family: a substitution containing fresh parameters through which every solution factors. It must not guess a unit for either variable.

Syntactic decomposition treats multiplication as an ordered constructor and therefore cannot respect δϵ=ϵδ. Solving for a variable of exponent ±1 repairs the first example: δ=Lϵ1. A single powered variable already shows the integer obstruction. For n>0, the equation zn=c is the coefficient family nz(g)=c(g)(gBD), so it has a solution exactly when n divides every coefficient c(g). With several variables, divisibility may become visible only after a change of integer basis. For example, direct isolation fails on δ2ϵ3=L, where neither exponent is invertible in Z, although the principal family δ=L1η3, ϵ=Lη2 exists for a fresh parameter η. The row [2  3] records the exponents of (δ,ϵ) in this equation. Elimination needs an invertible column change that replaces this row by [1  0], exposing the gcd of 2 and 3. The Smith reduction constructed below performs that change for every integer matrix.

A square integer matrix is unimodular when its determinant is 1 or 1; equivalently, its inverse also has integer entries. Such a matrix changes an integer basis without changing the integer combinations it generates. The elementary row and column operations below are unimodular.

Bézout’s identity is the arithmetic step behind the first operation. Let a,b be not both zero. If both are nonzero, run the extended Euclidean algorithm on |a|,|b| with remainders 0r< the positive divisor. If its back-substitution coefficients are p0,q0, put p=sgn(a)p0,q=sgn(b)q0,pa+qb=gcd(a,b)>0. For b=0, take (p,q)=(sgn(a),0); for a=0, take (p,q)=(0,sgn(b)). This fixed routine assigns one output pair (p,q) to every ordered pair (a,b)(0,0).

Lemma 6.9 — Two-entry gcd reduction

Let a,bZ be not both zero and let g=gcd(a,b)>0. There is a unimodular integer matrix P such that P[ab]=[g0],[ab]PT=[g0].

Proof of Lemma 6.9 — Two-entry gcd reduction

Proof. Bézout’s identity gives p,qZ with pa+qb=g. Take P=[pqb/ga/g]. Its determinant is (pa+qb)/g=1, and direct multiplication gives both displayed equations. Thus the row or column pair (a,b) can be replaced by (g,0) using invertible integer operations. ◻

Lemma 6.10 — Dividing pivot

Every nonzero integer matrix is equivalent by unimodular row and column operations to a block matrix [d00B],d>0, in which d divides every entry of B.

Proof of Lemma 6.10 — Dividing pivot

Proof. Move a nonzero entry to the upper-left corner. Apply lemma 6.9 successively to the pivot and each other entry of its column using row operations, then to the pivot and each other entry of its row using column operations. The row operations that clear the first column may reintroduce entries to the right of the pivot; the column operations that clear the first row may reintroduce entries below it. We therefore alternate these two clearing phases. If a phase exposes an entry not divisible by the positive pivot, the next two-entry reduction replaces that pivot by a strictly smaller gcd. If every exposed entry is divisible by the pivot, subtracting the corresponding integral multiples clears it without changing the pivot or the already-clear companion line. Thus either the pivot strictly decreases or both the first row and first column become clear. Only finitely many decreases are possible, so the process ends with a clear first row and column and a positive pivot d.

Suppose an entry a of the remaining block is not divisible by d. Add its column to the first column. That first column now contains both d and a. The two-entry reduction replaces the pivot by gcd(d,a)<d; clear the first row and column again. Each repair strictly decreases the positive pivot, so only finitely many repairs occur. At termination the pivot divides every entry of the remaining block. ◻

After ordering the base dimensions, an exponent map is a vector in Zm. An integer lattice is a subgroup of Zm generated by integer linear combinations of finitely many vectors. The exponent vectors of the chosen base dimensions generate the whole integer lattice Zm. Multiplication by a matrix in GLm(Z) replaces one ordered integer basis by another. For example, relative to the basis (L,T), the proposed basis (L,LT1) has column matrix [1101],det[1101]=1. It therefore generates the same integer lattice. Explicitly, for every a,bZ, LaTb=La+b(LT1)b.

Lemma 6.11 — Smith reduction over the integers

For every integer m-by-n matrix M, integer row and column operations produce unimodular matrices UGLm(Z) and VGLn(Z) such that UMV=S=diag(s1,,sr,0,,0),0<s1s2sr. This diagonal matrix S is a Smith normal form. Thus GLm(Z) is the group of m-by-m unimodular integer matrices under multiplication.

Proof of Lemma 6.11 — Smith reduction over the integers

Proof. Induct on min(m,n). The zero matrix is already in the required form. For a nonzero matrix, lemma 6.10 gives M[s100M1],s1>0,s1(M1)ij for all i,j. Apply the induction hypothesis to M1, using operations confined to its rows and columns. Because every entry of M1 is a multiple of s1, all integer combinations created by those operations remain multiples of s1. The first new positive pivot s2 is therefore divisible by s1; the same argument repeats in each smaller block. This produces 0<s1sr and a zero residual block.

Every operation used in lemma 6.9, lemma 6.10 has a unimodular elementary matrix. Multiplying the recorded row matrices and column matrices gives U and V. Only existence of this diagonal form is used below; uniqueness of its invariant factors is not claimed here. ◻

Definition 6.12 — Principal dimension solver

The principal dimension solver returns a solution through which every solution of the same dimension equations factors. Fix unknown dimension variables δ¯=(δ1,,δn), and let Gr be the finite set of dimension variables declared rigid. For a finite ordered system E=(di=Dei)i=1m, move unknown-variable factors to the left and base-dimension factors to the right: j=1nδjMij=ci,Mij=di(δj)ei(δj),ci=gBGrgei(g)di(g). The list δ¯ is exactly the set of dimension variables occurring in E that the solver is permitted to instantiate. Base dimensions and any dimension variables explicitly declared rigid are moved to the right-hand constants instead. Thus no variable occurring in an equation is silently neither solved nor declared rigid. The inference system of this chapter takes Gr= and declares every occurring dimension variable solvable; the rigid clause is recorded for uses of the solver under an ambient scheme or annotation that fixes selected variables. Thus M has integer entries, while the unknown vector zj=δj[ρ] and the right-hand vector ci have entries in the dimension group. The notation Mz=c abbreviates the multiplicative equations (Mz)i=jzjMij=ci; integers act by taking powers.

Compute UMV=S as in lemma 6.11, put z=Vz, and c=Uc, where integer matrices act on group-valued vectors by the same power-and-product convention. Each pivot row is (zi)si=ci. It has a solution exactly when si divides every generator exponent occurring in ci; a zero row requires ci=1. The coordinates zj corresponding to zero columns of S are unconstrained; name them by fresh dimension parameters η¯. Solve the pivots, substitute back through z=Vz, and call the resulting substitution ρE.

A substitution θ solves E when di[θ]=Dei[θ] for every displayed equation. It is a Gr-relative solution when it solves E and fixes every declared rigid variable: γ[θ]=γ for γGr. Every occurrence of “solution” in the solver contract below means this relative solution. A base dimension bB is not a substitution variable, so every substitution satisfies b[θ]=b.

The solver uses the following fixed routine. In each active block, choose the first nonzero entry in row-major order and move it to the upper-left corner. Clear the active column from top to bottom and the active row from left to right, using the canonical extended-gcd coefficients fixed above. If the pivot fails to divide the residual block, repair it with the first offending entry in row-major order and restart those two scans. Normalize every pivot to be positive before recursing on the lower-right block. Allocate parameters to zero columns from left to right using the global dimension-variable supply. The supply begins above every dimension variable in the input equations and the rigid set. If the caller supplies a finite protected set P, it also begins above every variable in P. Hence the ordered input tuple (E,Gr,P,supply) determines (U,V,ρE,supply). Other Smith reductions still produce mutually instantiable principal answers by theorem 6.13.

For example, solve δϵ=L while declaring ϵ rigid. Then δ¯=(δ), the matrix is [1], and the right-hand constant is Lϵ1. The solver returns δLϵ1 and leaves ϵ fixed. Without the rigid declaration the same equation instead returns a one-parameter family.

Here is the promised matrix calculation. For δϵ=L, M=[11],z=[δϵ],c=[L]. Take U=[1],V=[1101],UMV=[10]. The transformed equation fixes z1=L and leaves z2=η free. Since z=Vz, δ[ρE]=Lη1,ϵ[ρE]=η. Every concrete solution chooses a dimension for η. A different legal Smith reduction may print a different parameterization, but theorem 6.13 shows that the results are mutual instances on the variables of E. For δ2=L, the matrix is [2]; its pivot equation z2=L fails because 2 does not divide the exponent 1 of L.

For a genuinely nontrivial Smith step, take δ2ϵ3=L. Here M0=[23]. Execute the column algorithm rather than guessing its change of basis: M0=[2  3],C2C2C1,M1=[2  1],C1C2,M2=[1  2],C2C22C1,M3=[1  0]. The corresponding elementary matrices multiply to V=[1101][0110][1201]=[1312],M0V=[10]. Since det(V)=1, this is a legal unimodular column transformation. With z=Vz, the transformed equation fixes z1=L and leaves z2=η. Substitution back gives δ[ρE]=(z1)1(z2)3=L1η3,ϵ[ρE]=z1(z2)2=Lη2, whose exponents verify δ2ϵ3=L. This is the same style of Smith calculation used in exercise 6.7, whose matrix is instead [4  6]. The two legal parameterizations illustrate the mutual factorization clause of theorem 6.13. The two columns satisfy [2  3](1,1)T=1,[2  3](3,2)T=0. Thus the first column gives the pivot and the second spans the homogeneous integer solutions.

Row operations become visible in a two-equation system. Consider δ2=L2,δ2ϵ4=L2T4. Its matrix and right-hand vector are M=[2024],c=[L2L2T4]. Apply R2R2R1. Then U=[1011],V=I,UMV=[2004],Uc=[L2T4]. Here the second entry of Uc is the group quotient (L2T4)(L2)1=T4, not an additive subtraction. The pivot chain is 24, and the transformed equations are (z1)2=L2 and (z2)4=T4. They give δ=L and ϵ=T. Replacing the second right-hand side by L2T2 makes the second pivot fail because 42.

Theorem 6.13 — Dimension-solver soundness and principality

If the solver returns ρE, then it is a Gr-relative solution of E. For every other Gr-relative solution θ, there is a substitution ψ for the fresh parameters that fixes Gr, such that θ={δ1,,δn}ρE;ψ. Here (δ1,,δn) is the ordered unknown list fixed in definition 6.12; the restricted equality means agreement on exactly that list. Both sides already fix the declared rigids. The solver reports failure exactly when E has no Gr-relative solution.

Proof of Theorem 6.13 — Dimension-solver soundness and principality

Proof. Invertible integer row operations preserve the solution set of Mz=c, and the change of variables z=Vz is bijective because V1 is integral. The diagonal system separates into equations (zi)si=ci. Such an equation has a solution in the free abelian group exactly when si divides every generator coefficient of ci; a zero row reads 1=ci. These are precisely the failure tests in definition 6.12.

The dimension group is torsion-free: if zsi=(z)si for si>0, then z=z, coefficient by coefficient in its free abelian basis. Hence a passing pivot equation has exactly one solution. Division fixes each pivot coordinate and the remaining coordinates are arbitrary. Naming them η¯ gives ρE, so substitution back through V proves soundness. Any solution of the diagonal system chooses values for exactly those free coordinates. Define ψ by mapping each ηi to the coordinate selected by θ and by fixing every declared rigid. Since z=Vz is bijective, substitution back gives δj[θ]=δj[ρE;ψ](1jn). Because the matrix construction never substitutes for a declared rigid, ρE fixes Gr. This proves principality and completeness in the postfix convention of chapter 3. ◻

Corollary 6.14 — Integer-exponent Buckingham π count

Let the dimension vectors of n quantities be the columns of an integer matrix D of rank r over Q. The integer kernel of D has rank nr. Each kernel vector v gives the formal dimensionless monomial jqjvj, and a Smith basis gives nr independent such monomials. For a numerical interpretation, require qj0 whenever vj<0.

Proof of Corollary 6.14 — Integer-exponent Buckingham π count

Proof. Smith reduction sends D by invertible integer changes of basis to a matrix with r nonzero pivots and nr zero columns: invertibility of U,V over Q preserves rank, so the pivot count is r. Writing UDV=S gives Dv=0 iff S(V1v)=0. Thus the last nr columns of V, rather than the literal zero columns of S, form a Z-basis of the original integer kernel. Their coordinates freely parameterize that kernel, and Dv=0 says exactly that the monomial’s base-dimension exponents all vanish. This lattice statement is the integer-exponent form of the Buckingham π theorem. ◻

For a pendulum, order the quantities as period p, length l, and acceleration g. Their L,T exponent columns have kernel generated by (2,1,1), so p2g/l is dimensionless.

Now restrict to positive quantities. A positive change of length and time coordinates has the form p=tp,l=λl,g=λt2g(t,λ>0). Two positive triples are connected by such a coordinate change exactly when their values of p2g/l agree. For the reverse implication, take t=p/p and λ=l/l. Equality of the two monomials gives g=ll(pp)2g=λt2g, which is the transformed acceleration. A ternary relation R on positive triples assigns a truth value to each triple; a unary predicate Φ on R>0 assigns a truth value to each positive scalar. The relation R is invariant under every such coordinate change exactly when some Φ satisfies R(p,l,g)Φ(p2g/l). For the small-angle pendulum model, the additional physical law is p=2πl/g, so p2g/l=4π2. Square root and the constant π belong to that physical model, not to the integer-power source calculus.

Lemma 6.15 — Composing principal dimension solves

Fix one rigid set Gr. Suppose the parameters introduced by ρE are fresh for vars(EF), ρE is principal among Gr-relative solutions of E, and after applying it, ρF is principal among relative solutions of F[ρE] that still fix Gr. Then ρE;ρF fixes Gr and is principal for EF, with factorization equality on the ordered list of all nonrigid dimension variables occurring in EF.

Proof of Lemma 6.15 — Composing principal dimension solves

Proof. Alpha-rename the finitely many parameters of ρE away from vars(F) before forming the second problem. The renaming preserves the equations and the factorization clause of theorem 6.13. The composite fixes the common rigid set. It solves E because every substitution composed after ρE that fixes Gr preserves its equations, and it solves F because ρF solves the image system. Let θ be a Gr-relative solution of EF. Principality for E factors θ=vars(E)ρE;ψ; extend ψ to agree with θ on variables occurring only in F. Then ψ solves F[ρE], so it factors through ρF. Composing the two factors gives the required factorization on the variables constrained by the second problem. If a fresh parameter η introduced by ρE does not occur in F[ρE], then ρF fixes it; extend the residual factor by ηη[ψ]. If it does occur, the second factorization already determines the same image. This support extension preserves the first factorization and yields the required factorization through ρE;ρF on every variable of EF. ◻

Principal inference

The inference algorithm is Algorithm W from chapter 3 with one larger type unifier and four arithmetic clauses. We state the delta exactly.

Definition 6.16 — Dimension-aware inference

The judgment IU(Γ,e)=(S,τ) uses the variable, lambda, application, and let clauses of W. Its unifier munifyP takes a finite protected set P, a finite list of type equations, and a dimension store. It decomposes arrows and eliminates ordinary type variables as in chapter 3. Every equation Num[d]Num[e] is placed in a list D of dimension equations as d=De. Let E be the pending type equations. Decompose E until no type equation remains, then solve D once by ρD. Distinct type constructors clash. Thus a single unifier call uses one Smith reduction, while unifier calls made at different syntax nodes compose their answers in W’s ordinary left-to-right order. Lemma 6.15 proves that this incremental composition remains principal.

Explicitly, its essential clauses are shown with the fixed subscript P suppressed: munify(τ1τ2ρ1ρ2,E;D)=munify(τ1ρ1,τ2ρ2,E;D),munify(ατ,E;D)=[τ/α];munify(E[τ/α];D)(αftv(τ)),munify(Num[d]Num[e],E;D)=munify(E;D,d=De),munify(;D)=ρD. An occurs check rejects the second clause when its side condition fails; distinct outer constructors clash. Eliminating an ordinary type variable applies its image to both the remaining type equations and every dimension expression nested inside them. Once the type list is empty, one call to definition 6.12 solves the accumulated store D.

Fresh ordinary type variables and fresh dimension variables come from two disjoint indexed supplies. Before a run, each counter is larger than the index of every variable in the input environment, term annotation, equation lists, and protected set P. Consequently no variable allocated by the run belongs to P. A Smith call consumes its free parameters from the dimension supply from left to right; later recursive calls receive the unused suffix. Thus generated variables are fresh for the complete input and are never reused by a sibling call. Recording both initial counters determines every provisional variable and every Smith parameter in an inference trace. The notation munifyP(E;D) denotes this run with P fixed before allocation. Calls written munify(E) below abbreviate munify(E;).

Write I for IU. The new synthesis clauses are:

  1. q@u returns (id,Num[du]).

  2. For e1+e2, compute (S1,τ1)=I(Γ,e1),(S2,τ2)=I(Γ[S1],e2),U=munify(τ1[S2]Num[δ],τ2Num[δ]) for fresh δ, and return (S1;S2;U,Num[δ[U]]).

  3. Multiplication and division use the same first two calls, then choose fresh δ1,δ2 and compute U=munify(τ1[S2]Num[δ1],τ2Num[δ2]). Return S1;S2;U together with, respectively, Num[δ1[U]δ2[U]]orNum[δ1[U]δ2[U]1].

  4. For en, compute (S,τ)=I(Γ,e), choose fresh δ, and put U=munify(τNum[δ]). Return (S;U,Num[δ[U]n]).

At let, solve the bound expression before generalizing every ordinary and dimension variable absent from the substituted environment.

Lemma 6.17 — Termination of dimension-aware unification

For every finite P, the procedure munifyP(E;D) terminates for finite, well-sorted equation lists E,D.

Proof of Lemma 6.17 — Termination of dimension-aware unification

Proof. Use the lexicographic triple from lemma 3.24 on the type equation list: its number of ordinary type variables, its constructor count, and its length. Ordinary-variable elimination and constructor decomposition decrease the first or second component. Moving a numeric equation to D strictly shortens E; although D grows, the procedure never recurses on that store. When E is empty, Smith reduction terminates by lemma 6.11 and returns or fails. These clauses exhaust the recursion. ◻

Theorem 6.18 — Mixed-unifier contract

Fix a finite protected set P before the unifier allocates any variable. Let E be a finite list of well-sorted type equations and let D be a finite list of dimension equations. A two-sorted substitution Q solves (E;D) when τ[Q]=Dυ[Q] for every τυ in E and d[Q]=De[Q] for every d=De in D. The procedure munifyP has the following properties.

  1. If munifyP(E;D)=S, then S solves (E;D).

  2. If Q solves (E;D) and the procedure returns S, there is a two-sorted substitution R such that Q=vars(E,D)S;R.

  3. The procedure reports failure if and only if (E;D) has no solution.

  4. The returned substitution fixes every variable in Pvars(E,D). The residual R in item 2 can be extended so that the same factorization holds on vars(E,D)P without changing it on the problem variables.

Proof of Theorem 6.18 — Mixed-unifier contract

Proof. Induct on the lexicographic termination measure of lemma 6.17. Maintain the stronger claim containing all four clauses.

Reflexive and arrow cases. A reflexive equation is deleted. An arrow equation is replaced by its domain and codomain equations. Structural type equality makes the old and new solution sets identical, so the induction hypothesis proves all four clauses.

Ordinary-variable elimination. Consider ατ with αftv(τ). Every solution Q satisfies α[Q]=τ[Q] and therefore factors through [τ/α]: define the residual to agree with Q away from α. Substitution of [τ/α] in the remaining equations is sound in both sorts because ordinary substitution acts structurally on every numeric type and leaves the dimension store sorted. Conversely, any solution of the substituted problem composed after [τ/α] solves the original equation and the remaining list. The occurs-check failure is exact: a finite type tree cannot equal a proper subtree containing itself. Orienting τα to this case does not change the solution set.

Numeric collection. Replacing Num[d]Num[e] by d=De in the store preserves the solution set by injectivity of the numeric type constructor. The induction hypothesis therefore applies to the shorter type list. Distinct outer constructors have no common instance by lemma 6.8, so constructor clash is exact failure.

Dimension store. When the type list is empty, theorem 6.13 gives soundness, exact failure, and factorization for the accumulated store. Its substitution is the identity off the store variables and its fresh parameters. Those parameters avoid P because the initial dimension-supply counter is larger than every index occurring in P. This proves the support clause in theorem 6.18(4).

Composing the one-variable eliminations in their execution order with the final dimension substitution proves items 1–3 for the initial problem. For item 4, let γPvars(E,D). The returned substitution fixes γ, so extend R by γ[R]:=γ[Q]. This changes no problem-variable image and gives γ[S;R]=γ[Q]. Repeating the construction for the finite set P proves protected factorization. ◻

Example 6.19 — A program that generates a coupled dimension equation

Run inference on λx.λy.(xy)+3@m. The two binders receive provisional numeric dimensions δ and ϵ. Multiplication synthesizes Num[δϵ]; the literal synthesizes Num[L]; and the addition clause therefore hands the dimension solver the genuinely coupled equation δϵ=DL. Its principal answer is the one-parameter family computed above. Thus the Smith solver is required by programs generated by the printed inference clauses; the worked algebra calculation is one instance of that general argument.

Example 6.20 — A complete dimension-inference trace

Infer let s=λx.xx in s(3@m). The lambda clause gives x fresh ordinary type α. The multiplication clause introduces fresh dimension variables δ1,δ2 and equations αNum[δ1],αNum[δ2]. Eliminating α leaves δ1=Dδ2; its principal dimension solution sends both to one fresh parameter η. Thus the definition has monotype Num[η]Num[η2], and let-generalization gives s:η.Num[η]Num[η2]. The body instantiates η at fresh δ3. Since 3@m:Num[L], application generates δ3=DL and fixes its result to Num[L2]. Every variable named here is determined by the two supplies declared in definition 6.16.

The substitution order is now visible in every binary clause: the right operand sees Γ[S1], and S2 acts on the left operand’s type before the common unifier is called. Omitting either action can lose a constraint on a variable inherited from Γ.

Theorem 6.21 — Principal dimension inference

For a well-formed environment Γ:

  1. if IU(Γ,e)=(S,τ), then Γ[S]e:τ;

  2. if Γ[T]se:τ, then inference succeeds with (S,τ), and there is a substitution R such that T and S;R agree on Γ while τ=Dτ[R].

By lemma 6.7, the completeness clause also applies to declarative monotype typings. Consequently generalizing the inferred type gives a principal scheme.

Proof of Theorem 6.21 — Principal dimension inference

Proof. Prove soundness and protected completeness simultaneously by induction on the source term. The strengthened completeness statement quantifies over every finite protected set P fixed before the induction begins. At each syntax node, invoke munifyP with this same P. Every generated variable avoids P, the target substitution, and the target derivation, while theorem 6.18(4) preserves the inherited images of variables in P. The algorithm stated in definition 6.16 is the instance P=.

Variable and abstraction. The variable clause instantiates its stored prefix with fresh variables. A target instance determines the residual images of exactly those variables; the two prefixes are first standardized apart. For an abstraction, assign its binder a fresh ordinary variable α and apply the induction hypothesis to the body while protecting the image of the ambient protected set. The returned type is α[S]τ, and type substitution applied to the premise reconstructs both soundness and the target arrow.

Application. The recursive calls give Γ[S1;S2]e1:τ1[S2],Γ[S1;S2]e2:τ2. The mixed unifier U solves τ1[S2]τ2β by theorem 6.18(1). Applying U to both derivations and using App yields result β[U] under Γ[S1;S2;U]. For completeness, the first protected induction hypothesis factors the target through S1. Apply the second while also protecting ftv(τ1) and fdv(τ1); the target substitution then solves the application equation. Items 2 and 4 of theorem 6.18 factor it through U without changing an inherited protected image.

Let. Soundness of the definition gives Γ[S1]e1:τ1. Generalize exactly the ordinary and dimension variables absent from Γ[S1], apply S2 to that declarative derivation, and combine it with the body induction hypothesis by Let. For completeness, standardize both quantified sorts away from the target derivation. The target instance determines their residual images, while the body induction hypothesis preserves the variables free in the substituted environment. No arithmetic premise is hidden in generalization.

Addition. Put Γ12U=Γ[S1;S2;U]. The recursive soundness derivations, after the indicated substitutions, have types Γ12Ue1:τ1[S2][U],Γ12Ue2:τ2[U]. The exact equations solved by U give τ1[S2][U]=Num[δ[U]]=τ2[U]. Rule D-Add therefore derives the returned type. Conversely, inversion of a target D-Add derivation gives one dimension d for both operands. The two protected induction hypotheses make the residual target substitution solve the same mixed equations. The factorization clauses of theorem 6.18 produce the required residual after U.

Multiplication and division. The same context Γ12U types the operands at τ1[S2][U]=Num[δ1[U]],τ2[U]=Num[δ2[U]]. D-Mul and D-Div return, respectively, Num[δ1[U]δ2[U]]andNum[δ1[U]δ2[U]1]. In the reverse direction, inversion exposes the two target operand dimensions. Protected recursive factorization handles the recursive calls. Items 2 and 4 of theorem 6.18 factor the two numeric equations. The group-homomorphism laws preserve product and inverse in the result.

Power and literal. A literal returns its declared closed dimension. For power, recursive soundness followed by U types the operand at Num[δ[U]], and D-Pow returns Num[δ[U]n]. Target inversion and mixed-unifier factorization prove completeness; dn[ρ]=d[ρ]n identifies the result. These cases exhaust the term grammar. Structural recursion and lemma 6.17 terminate every call, and the protected claim at the empty set gives the theorem. ◻

Exercise 6.3

★★☆ Trace inference for let s=λx.xx in let a=s(3@m) in s(2@s). List the provisional ordinary type, every fresh dimension variable, the equations generated while typing the definition and both applications, their principal substitutions, and the generalized scheme for s. Record the monotype assigned to a and the type of the whole term. Exhibit the two distinct instantiating substitutions used at the two variable occurrences of the term variable s.

Elaboration and type safety

Scales affect numbers, not dimensions. We make their use explicit by elaborating every literal to a canonical-unit core.

Definition 6.22 — Canonical numeric core

The canonical numeric core represents every literal in canonical units. Its types are the source types. Let {+,,/}. Core terms, values, and call-by-value evaluation contexts are a::=xqdλ(x:τ).aaalet x=a in aaaanaritherr,v::=qdλ(x:τ).a,E::=[]EavElet x=E in aEavEEn. Define the one-frame contexts by F::=[]av[]let x=[] in a[]av[][]n. A one-frame context exposes only the next error-propagation position; iterating these frames gives the evaluation contexts E. A core typing context Δ maps term variables to monotypes, never to schemes.

Definition 6.23 — Core typing

A core value is any term generated by v in definition 6.22; in particular, a core numeric value is qd:Num[d]. The error aritherr is not a value and has any result type; it records an ordinary arithmetic-domain failure, not a dimension mismatch: XΔaritherr:τCArithErr. The functional core has monomorphic variables and monomorphic let:

Δ(x)=τ
Δx:τ
C-Var
Δ,x:τa:υ
Δλ(x:τ).a:τυ
C-Lam
Δa1:τυΔa2:τ
Δa1a2:υ
C-App
Δa1:τΔ,x:τa2:υ
Δlet x=a1 in a2:υ
C-Let
Δqd:Num[d]
C-Lit
Δa1:Num[d]Δa2:Num[d]
Δa1+a2:Num[d]
C-Add
Δa1:Num[d1]Δa2:Num[d2]
Δa1a2:Num[d1d2]
C-Mul
Δa1:Num[d1]Δa2:Num[d2]
Δa1/a2:Num[d1d21]
C-Div
Δa:Num[d]
Δan:Num[dn]
C-Pow

Core conversion is D-Conv with e replaced by a. Core term substitution a[v/x] is the capture-avoiding named substitution of definition 1.58; it descends through every core constructor, alpha-renames either binder when required, and leaves type and dimension annotations unchanged.

Definition 6.24 — Core dynamics

The two functional roots are value restricted: (λ(x:τ).b)vb[v/x],let x=v in bb[v/x]. The arithmetic roots include pd+qdp+qd,pd1qd2pqd1d2, Division uses rational quotient and dimension d1d21 when q0; an integer power uses coefficient qn and dimension dn when the rational power is defined. In particular, exponent zero is total, including at zero: qd011. Division by zero, and zero raised to a negative power, reduce respectively by pd/0earitherr,0dnaritherr(n<0). Evaluation is call by value, and the one-frame rule Faritherraritherr propagates the outcome outward exactly one frame at a time. Using F rather than an arbitrary nonempty E prevents a nested error from having both a one-frame and an all-frames propagation step. The compatible closure is FaFa whenever aa. Iterating frames yields exactly the full contexts E above. Write aa for the reflexive–transitive closure. A core normal form has no outgoing step. A core neutral is a core term that is neither a core value nor aritherr; a neutral normal form is both core neutral and a core normal form. A terminal outcome is a core value or aritherr. For example, typing fixes both successful and failing calculations: 1L+2L:Num[L],1L+2L3L, whereas 1L/0T:Num[LT1],1L/0Taritherr. The first result carries the dimension required by C-Add. The second records a zero-denominator failure at the result type required by C-Div; incompatible dimensions never reach this core because source typing rejects them. Write ao when ao and o is a terminal outcome. A step relation is deterministic when one term cannot step to two different successors.

Source let-polymorphism cannot be copied into C-Let: substituting one core value for a variable used at two distinct monotypes would make preservation false. Elaboration therefore specializes source let-bound definitions before core evaluation.

For a two-sorted substitution θ, let a[θ] apply θ to every core type and dimension annotation. A template environment Θ matching Γ over Δ assigns to every declaration x:α¯δ¯.τ0 and every well-sorted instance θ of its prefix a core term Θ(x)(θ) such that ΔΘ(x)(θ):τ0[θ]. It also satisfies the two context-stability conditions ftv(Δ)ftv(Γ),fdv(Δ)fdv(Γ), where variables bound by a scheme prefix are not free in Γ. Hence if Qt and Qd are the variables generalized from a type over Γ, then Qtftv(Δ)=,Qdfdv(Δ)=. The judgment ΓΘ;ΔUD:e:τa elaborates the displayed syntax-directed source derivation D. Its variable, literal, lambda, application, and let clauses are

Γ(x)=α¯δ¯.τ0θ instantiates α¯,δ¯Θ(x)(θ)=a
ΓΘ;ΔUx:τ0[θ]a
E-Var
U(u)=(su,du)
ΓΘ;ΔUq@u:Num[du]qsudu
E-Lit
Γ,x:τ;Θ,x(x);Δ,x:τUD:e:υa
ΓΘ;ΔUλx.e:τυλ(x:τ).a
E-Lam
ΓΘ;ΔUD1:e1:τυa1ΓΘ;ΔUD2:e2:τa2
ΓΘ;ΔUe1e2:υa1a2
E-App
ΓΘ;ΔUD1:e1:τ1a1Qt=ftv(τ1)ftv(Γ)Qd=fdv(τ1)fdv(Γ)σ=QtQd.τ1Γ,x:σΘ,x(θa1[θ]);ΔUD2:e2:τ2a2
ΓΘ;ΔUlet x=e1 in e2:τ2a2
E-Let

The arithmetic clauses preserve their source constructor and recursively elaborate their premises. E-Let emits no runtime let: each E-Var node for x in the finite derivation D2 emits the required annotated instance of a1. For a fixed derivation D, write elabU(D) for its unique output up to alpha-renaming. This notation is deliberately derivation directed; an unannotated source lambda does not by itself determine a core annotation.

For example, a derivation of let x=λy.y in let z=x(1@m) in (λw.x(1@s))z uses x at dimensions L and T. Template expansion elaborates it to the following term, where Id:=λ(y:Num[d]).y: (λ(w:Num[L]).IT1T)(IL1L). The right application frame first selects the beta redex inside the argument. After that contraction, the outer and final annotated beta roots yield (λ(w:Num[L]).IT1T)1LIT1T1T. The two copies of the source identity have different core annotations, while every runtime binder remains monomorphic.

The simpler unit calculation elaborates as elabU(Dsum)=1L+1L2L. Here Dsum is the unique syntax-directed derivation of 100@cm+1@m under the displayed unit environment. No cast is inserted between dimensions. Both literals already elaborate to the same canonical dimension and scale.

By the specialization semantics of this chapter, a closed syntax-directed derivation D executes with outcome o exactly when elabU(D)o. Thus source let binds a polymorphic template that is expanded at the finitely many E-Var nodes for its binder in D. In particular, a derivation of let x=(1@m)/(0@s) in 2@m contains no use of x. E-Let emits 2L, so this derivation executes to 2L; it does not evaluate the unused division.

Lemma 6.25 — Elaboration typing

If Θ matches Γ over Δ and ΓΘ;ΔUD:e:τa, then Δa:τ.

Proof of Lemma 6.25 — Elaboration typing

Proof. Induct on the elaboration derivation. E-Var is exactly the matching condition. E-Lit uses qsudu:Num[du]. In E-Lam, the trivial template for x matches the monomorphic declaration x:τ, so the induction hypothesis and C-Lam apply. E-App follows from its two induction hypotheses and C-App. The arithmetic cases reproduce the group operation in their result annotation.

For E-Let, the context-stability conditions give Qtftv(Δ)=,Qdfdv(Δ)=. A subsidiary induction on the core typing derivation for a1 applies θ to every annotation and gives Δa1[θ]:τ1[θ] for every instance θ of the two prefixes; the context is unchanged because their variables are absent from Δ. The extended source and template environments preserve the context-stability conditions: the new source scheme binds the prefix, while the core context is unchanged. Hence they match Γ,x:QtQd.τ1 over Δ. The body induction hypothesis yields Δa2:τ2, which is the emitted term and required result. ◻

Lemma 6.26 — Core substitution and numeric canonical forms

The canonical numeric core has the following properties.

  1. If Δ,x:σa:τ and Δv:σ, then Δa[v/x]:τ.

  2. If Δa:τ and θ is a well-sorted ordinary-type and dimension substitution, then Δ[θ]a[θ]:τ[θ].

  3. If v is a closed value and v:Num[d], then v=qd for some qQ.

Proof of Lemma 6.26 — Core substitution and numeric canonical forms

Proof. For item 1, induct on the first typing derivation after freshening binders away from x and fv(v). Dimension annotations are not term syntax and remain unchanged; every nonbinding constructor reapplies its rule to the induction hypotheses, while variable, lambda, and let use the capture-avoiding clauses.

For item 2, induct on the core typing derivation. Each rule is stable under sorted substitution; in C-Lam and C-Let the substitution acts on the binder’s monotype as well as on the body annotations. Normalized dimension equality is preserved by dimension substitution, so the conversion case reapplies C-Conv.

For item 3, normalize a final conversion and inspect the value grammar. Lambdas have arrow type and numeric literals have their displayed annotation; lemma 6.8 prevents conversion from changing either outer constructor. ◻

Lemma 6.27 — Unique core decomposition

Every core term is a terminal outcome, a neutral normal form, or has exactly one decomposition a=Er, where E is an evaluation context and r is one of the following redexes:

  1. one of the beta and value-let roots in definition 6.24;

  2. a numeric success root, a division with zero denominator, or zero to a negative power, as specified in definition 6.24;

  3. Faritherr for one frame F.

The three redex classes are pairwise disjoint, and every redex has exactly one successor.

Proof of Lemma 6.27 — Unique core decomposition

Proof. Induct on the term. A variable is a neutral normal form; a numeral and an abstraction are values; and aritherr is a terminal outcome. For an elimination, the selected subterm and the next frame are fixed by outer termfirst selectionselection after a left valuea1a2a1 through []a2a2 through v[]let x=a1 in a2a1 through let x=[] in a2value-let roota1a2a1 through []a2a2 through v[]a1na1 through []npower root. If the selected subterm has a decomposition, its unique context and redex lift through the listed frame. If it is aritherr, the listed frame gives the unique one-frame propagation redex. A selected neutral normal form makes the outer term neutral and normal.

It remains to inspect values. In an application, a lambda operator gives the unique beta root; a numeral operator leaves a neutral normal form. A let with a value definition gives the value-let root. Addition gives a root exactly for two numerals with the same dimension annotation; multiplication and division give a root for two numerals; power gives a root for one numeral. The zero-denominator and negative-power cases select the error root, and every other numeric case selects its unique success root. Any remaining value shape leaves a neutral normal form. The listed outer constructors, frame positions, and root shapes are disjoint, so both decomposition and successor are unique. ◻

Theorem 6.28 — Core preservation and progress

If a:τ, then a is a value, a=aritherr, or it takes one deterministic core step; every such step preserves τ.

Proof of Theorem 6.28 — Core preservation and progress

Proof. First prove preservation for an arbitrary context Δ by induction on the step derivation, peeling any final C-Conv from the typing derivation before the corresponding case. Beta and value-let use lemma 6.26(1). The arithmetic roots preserve the following result annotations: rootresult typepd+qdNum[d]pd1qd2Num[d1d2]pd1/qd2Num[d1d21]qdnNum[dn]. The two arithmetic error roots have the same types as their successful rows by C-ArithErr. For compatible closure, inversion fixes the type of the selected subterm; the induction hypothesis preserves that type, and the rule in the right column rebuilds the surrounding judgment: framerebuilding rule[]a2,v[]C-Applet x=[] in a2C-Let[]+a2,v+[]C-Add[]a2,v[]C-Mul[]/a2,v/[]C-Div[]nC-Pow. An error-propagation root has the surrounding result type by C-ArithErr. If the original typing ended in C-Conv, reapply C-Conv to the preserved premise.

Next prove progress by induction on the closed typing derivation. A variable case is impossible; numerals and lambdas are values; and aritherr is a terminal outcome. For an application, first use the operator induction hypothesis. An operator step lifts through []a2, and an operator error propagates. If the operator is a value, use the argument induction hypothesis through v[]. When both are values, arrow canonical forms make the operator a lambda, so beta applies. A let evaluates its definition through its frame; a value exposes value-let, and an error propagates.

For binary arithmetic, inspect the left operand and then the right operand. An operand step lifts through its listed frame, and an error propagates. Numeric canonical forms make closed numeric values numerals. C-Add gives two numerals with the same annotation; C-Mul and C-Div give two numeral operands; C-Pow gives one. Division selects its success root when the denominator is nonzero and its error root when it is zero. Power selects the negative-zero error root exactly when q=0 and n<0, and otherwise selects its success root. These cases exhaust the typing rules.

Finally, suppose aa and aa. Lemma 6.27 gives one evaluation position and one redex, and gives that redex one successor. Hence a=a, so the relation is deterministic. Preservation gives every successor type τ. ◻

Corollary 6.29 — Source dimensional safety

Every syntax-directed derivation produced for a closed source term accepted by inference elaborates from the empty template environment to a core term that does not become stuck because two arithmetic operands have incompatible dimensions.

Proof of Corollary 6.29 — Source dimensional safety

Proof. Principal inference supplies the source derivation, and elaboration typing makes its empty-environment elaboration well typed. Core safety then classifies every reachable normal form as a value or aritherr; neither is a dimension-mismatch stuck state. ◻

Exercise 6.4

★☆☆ Elaborate 12@inch+1@ft under scales sinch=127/5000 and sft=381/1250, both at dimension L. Reduce the core sum and express the answer in canonical meters.

Changing units coherently

Choosing centimeters rather than meters as the canonical length unit changes the stored coefficient. It must not change the physical calculation.

The naive induction statement relates only numeric outcomes by q=χ(d)q. At an application its induction hypotheses say separately that the function and argument terminate, but say nothing about how the function responds to a rescaled argument. Thus the first higher-order case already stops at fABg,aAa⟸̸numeric equality alone. The repair is a binary, type-indexed comparison whose arrow clause tests every related input pair.

For this core, SN(a) means that there is no infinite chain a=a0a1. Core reduction is finitely branching, so for SN(a), write ν(a) for the maximum length of a reduction from a, as justified by lemma 2.47. The core-neutral class of definition 6.24 includes redexes and stuck eliminations; in particular, an open neutral normal form need not be a terminal outcome. Consequently every core normal form is exactly a value, aritherr, or a neutral normal form. The judgment ao from definition 6.24 supplies the observations in the comparison below.

Definition 6.30 — Coherent scale change

Write B for the free abelian group of closed dimensions generated by B. A scale character is a group homomorphism χ:BQ>0: concretely, choose one positive scale factor for each base dimension and extend multiplicatively. No representation-theoretic meaning of “character” is used. Unit environments U,U are χ-coherent when they assign every unit the same dimension and su=χ(du)su. The unit-change logical relation A is defined recursively on pairs of closed core values at each closed type A. Numeric values at closed dimension d are related when qdNum[d]qd iff q=χ(d)q. Define related outcomes at a closed type A by aritherrAaritherr,vAviffvAv. At an arrow, the closed values f,g satisfy fABg when, for every pair of closed values aAa, the two applications evaluate to related terminal outcomes: fao,gao,oBo. There are no other A pairs, and A is defined only on closed core values. Thus the arguments themselves change coordinates; this is a relational arrow clause, not equality on the same point. Monomorphic core value environments are related componentwise at their closed context types.

Fix a closing substitution κ for Γ and related closing core value environments γ,γ. Template environments Θ,Θ are χ-related at Γ[κ] over γ,γ when, for every x:Q.τ0 in Γ and every closed extension θ of κ to Q, the core terms Θ(x)(θ)[γ] and Θ(x)(θ)[γ] terminate at outcomes related by τ0[θ]. This condition compares specialized code, not a single polymorphic runtime value.

Lemma 6.31 — Saturation for dimension-core candidates

Extend the STLC candidate family by retaining its arrow clause and replacing its atomic clause by aRNum[d]SN(a)  qQd.(aqdd=d), so reduction to an error is permitted, while a reachable numeral must carry the candidate’s dimension. A neutral normal form satisfies the implication vacuously. For every closed core type A, the resulting family has:

  1. normalization: aRA implies SN(a);

  2. one-step reduction closure: if aRA and aa, then aRA;

  3. neutral expansion: if n is core neutral and every immediate reduct of n belongs to RA, then nRA;

  4. error membership: aritherrRA.

The family also admits the following core principal expansions. If v is a value and b[v/x]RB, then both (λ(x:A).b)v and let x=v in b belong to RB. For a numeric root, if its contractum is in the result candidate and its operands are strongly normalizing, then the numeric redex is in that candidate.

Proof of Lemma 6.31 — Saturation for dimension-core candidates

Proof. Induct on the result type, proving the four clauses in their displayed order. At Num[d], normalization is the first conjunct. If aa, then SN(a) implies SN(a), and every reduction of a to a numeral is a tail of a reduction of a. This proves reduction closure.

For neutral expansion, suppose every immediate reduct of n lies in the numeric candidate. Core syntax gives finitely many immediate reducts. Their reduction trees are well founded by the normalization clause, so adjoining the root n proves SN(n). If nqd, the sequence is nonempty because a neutral term is not a numeric introduction. Its first step reaches a candidate member, whose canonical-form implication gives d=d. The term aritherr is normal and reaches no numeral, which proves error membership at the numeric type.

At a closed arrow AB, choose a fresh variable zRA. For a numeric A, it is strongly normalizing and has no reduction to a numeral; for an arrow A, its membership follows from the already-proved neutral expansion clause at that proper subtype. If eRAB, then ezRB; an infinite reduction of e would lift to one of ez, proving normalization. Reduction closure follows by placing ee under application to an arbitrary member of RA and using reduction closure at B. For neutral expansion, fix aRA. Because the operator is neutral rather than a value, call-by-value evaluation can only step the operator: every immediate reduct of na is na with nn. The premise gives nRAB, so the arrow clause gives naRB. The application na is core neutral, and neutral expansion at B admits it. For error membership, fix the same argument. The only immediate step of aritherra is one-frame propagation to aritherr, which belongs to RB by the type induction hypothesis. Neutral expansion at B and the arrow clause give aritherrRAB. Closed numeric and arrow types exhaust the candidate indices; candidates are not defined at an open type variable.

For beta principal expansion, both the abstraction and its value argument are values, so the only immediate reduct of (λ(x:A).b)v is b[v/x]. The beta redex is core neutral; clause 3 admits it. A let with a value definition has only the corresponding substitution root b[v/x]. It too is core neutral with one immediate reduct in RB, so clause 3 proves value-let expansion.

For numeric principal expansion, induct on the sum of the maximal reduction heights of the operands. An operand step lowers that sum and gives a candidate immediate reduct by the induction hypothesis. When the operands are the numerals required by the root, its immediate root reduct is the contractum assumed to belong to the result candidate. If the selected operand is aritherr, the immediate propagation reduct is aritherr, which belongs to the result candidate. Hence every immediate reduct belongs. The redex is core neutral, so clause 3 puts it in the candidate. This covers addition, multiplication, division, and power. ◻

Lemma 6.32 — Fundamental lemma for the dimension core

Use the reducibility candidates of definition 2.39, lemma 6.31. Suppose Δa:τ. Let κ be a well-sorted substitution that maps every free ordinary type variable of Δ,τ,a to a closed type and every free dimension variable there to a closed dimension. If γ maps each declaration x:A in Δ to a core term γ(x)RA[κ], then a[κ][γ]Rτ[κ].

Proof of Lemma 6.32 — Fundamental lemma for the dimension core

Proof. Fix κ and induct on the core typing derivation. Every candidate index below is the closed image of the displayed type under κ. Variables use the corresponding component of γ; to reduce clutter, write A for A[κ] in candidate subscripts throughout the proof. Before an abstraction, alpha-rename its binder away from the free variables of every term in the finite range of γ. Let L:=λ(x:A[κ]).b[κ][γ]. To prove LRAB, fix an arbitrary rRA. Clause 1 of lemma 6.31 gives SN(r), so ν(r) is defined. Induct on ν(r) to prove LrRB. For every immediate step rr, reduction closure gives rRA and ν(r)<ν(r); the height induction therefore places the corresponding immediate reduct Lr in RB. If at least one such step exists, these are all immediate reducts of Lr, and core neutral expansion places Lr there.

Suppose instead that r is normal. By the definition of core neutral, either r=v is a value, r=aritherr, or r is a neutral normal form. In the value case, the typing induction hypothesis for the body applies to the realizing environment γ,xv, yielding b[κ][γ,xv]=αb[κ][γ][v/x]RB. Core beta principal expansion admits Lv. If r=aritherr, the sole step Lraritherr, followed by error membership and neutral expansion, admits the application. In the remaining case r is a neutral normal form. Call by value has neither an argument step nor a beta step, so Lr is neutral and has no immediate reduct; neutral expansion admits it vacuously. These cases prove the arrow clause for L without importing the compatible-beta argument of theorem 2.42.

For C-App, the two typing induction hypotheses give a1[κ][γ]RAB and a2[κ][γ]RA. The defining arrow clause gives a1[κ][γ]a2[κ][γ]RB, which is exactly the substituted application. A numeric literal after κ is strongly normalizing, and its only reachable numeral is itself with the annotation displayed by C-Lit. Rule C-ArithErr uses the fact that aritherr belongs to every result candidate. A final D-Conv does not change the candidate: normalized dimensions related by =D are equal maps, and the conversion clauses preserve the type tree.

For C-Let, the definition induction hypothesis gives a1[κ][γ]RA[κ]. Induct on the maximal reduction height of that closed definition. If it takes a step a1[κ][γ]a1, then ν(a1)<ν(a1[κ][γ]); the height induction puts let x=a1 in a2[κ][γ] in the result candidate. This term is precisely the reduct selected by the let evaluation frame. If the definition is a value v, one-step reduction closure puts vRA[κ]. The body induction hypothesis therefore applies with that value bound to x, and the let root contracts to the resulting candidate member. If it is aritherr, one-frame propagation reaches the error in the result candidate. If the definition is a neutral normal form, the let then has no immediate reduct and belongs to the result candidate by neutral expansion. Thus every immediate reduct of the let term belongs to the result candidate, and neutral expansion admits the let term itself.

Consider C-Div as a representative partial-arithmetic case. For reducible a1 and a2, induct on the sum of their maximal reduction heights. A step in the left operand, or in the right operand after the left is a value, decreases that sum. At normal operands, an error in the selected position propagates. A neutral normal left operand makes the whole division neutral and normal. If the left operand is a value, a neutral normal right operand does the same; a right error propagates. It remains to consider two values. For numerals pd1 and qd2, the root cases are pd1/qd2{p/qd1d21,q0,aritherr,q=0. Numeric principal expansion applies in both cases. If either value is a lambda, the division has no root, so the outer term is neutral and normal; neutral expansion admits it vacuously. Hence a1/a2RNum[d1d21] in every case.

For addition and multiplication, the same height induction follows their left-to-right frames. A selected error propagates. Two numeral values expose a total root with result annotation d for addition and d1d2 for multiplication; numeric principal expansion concludes. A selected neutral normal operand, or a lambda in either numeric position, leaves a neutral normal outer term. For power, induct on its operand height. A numeral gives qdn{aritherr,q=0 and n<0,11,n=0,qndn,otherwise. A lambda operand leaves a neutral normal form. Numeric principal expansion or neutral expansion therefore closes every added arithmetic clause. ◻

Lemma 6.33 — Termination of the dimension core

Every well-typed closed core term terminates at a value or aritherr.

Proof of Lemma 6.33 — Termination of the dimension core

Proof. Apply lemma 6.32 with the empty environment and the unique empty closing substitution for the closed term. Membership in every candidate entails strong normalization. Follow the deterministic step relation until its strongly normalizing reduction tree reaches a normal form. Core progress says that this normal form is a value or aritherr, and determinism makes it unique. Hence it is a terminal outcome reached by . ◻

Lemma 6.34 — One-step expansion of core evaluation

If aa and ao, then ao.

Proof of Lemma 6.34 — One-step expansion of core evaluation

Proof. The evaluation of a is a finite sequence ao ending in a value or aritherr. Prefix that sequence by aa; transitivity of the reflexive-transitive closure gives ao with the same terminal outcome. ◻

First define the scale erasure of a core term, written |a|s: replace every annotated numeral qd by the marker d, and recurse through every other core constructor. Now define erases recursively on source and elaboration derivations. At a D-Lit node, replace the lookup premise U(u)=(su,du) by (u,du). At every elaboration node whose conclusion ends in a, replace that output by |a|s; at E-Lit, also replace the lookup premise by (u,du). Retain every rule label, source term, source type, and other premise, and apply erases recursively to immediate subderivations. Two source/elaboration derivations are scale companions when erases(D)=erases(D). For example, companion E-Lit nodes for 2@u may carry su=1 and su=100 at dimension L, and therefore elaborate to 2L and 200L. Their erased nodes both retain (u,L) and conclude with L.

Theorem 6.35 — Unit-change invariance

Let U,U be χ-coherent.

  1. Suppose scale-companion syntax-directed derivations D,D elaborate as ΓΘ;ΔUD:e:τa,ΓΘ;ΔUD:e:τa. Let κ close every free ordinary type and dimension variable, and let closing value environments γ,γ be componentwise related at Δ[κ],Δ[κ]. If Θ,Θ are χ-related at Γ[κ] over γ,γ, then a[κ][γ] and a[κ][γ] terminate at outcomes o,o with oτ[κ]o.

  2. In particular, if scale-companion derivations D,D derive e:Num[d], their two empty-environment elaborations either both produce aritherr, or produce qd and qd with q=χ(d)q.

Proof of Theorem 6.35 — Unit-change invariance

Proof. For item 1, induct on the number of nodes in the common tree erases(D)=erases(D), pairing the two derivation nodes at each induction step and closing their annotations by κ. Elaboration typing and lemma 6.26(2) type both closed terms, and lemma 6.33 gives their unique outcomes. For a literal, qsu=qχ(du)su=χ(du)(qsu), so the elaborated values are related. In an arithmetic rule, the operand induction hypotheses first give related terminal outcomes. If they are errors, one-frame propagation produces an error on each side. Otherwise they are related numeric values. Addition uses the same closed dimension κ(d) on both operands and distributes the common factor χ(κ(d)). Multiplication uses homomorphism: χ(κ(d1d2))=χ(κ(d1))χ(κ(d2)); division and integer powers use the inverse and power laws. Positivity of every χ(d) gives q=0 iff χ(d)q=0, so division by zero and a negative power of zero produce aritherr on both sides, never on just one. The variable case is the χ-related-template hypothesis at the selected closed instance. For a lambda, choose related arguments vAv. The body induction hypothesis under value environments extended by xv,v gives related terminal outcomes for the substituted bodies. Each application takes one beta step to its body substitution, so lemma 6.34 supplies the evaluations required by the arrow clause.

For application, matching operator or argument errors propagate through the same frame on both sides. When both operators and both arguments terminate at related values, the arrow clause gives related application outcomes.

For E-Let, fix any closed instance θ of its generalized prefix. Apply the definition induction hypothesis with the closing extension θ of κ. Its two specialized definition terms terminate at related outcomes, so the extended template environments are χ-related at the generalized source declaration. The body induction hypothesis then compares the emitted terms directly. No runtime let step is involved: E-Let has already specialized and expanded every use in the finite source derivation. These cases exhaust the elaboration rules and prove item 1. Item 2 applies item 1 with empty template, core, and value environments, then uses the numeric clause of . ◻

For the same physical length, changing the canonical length scale from meters to centimeters uses χ(L)=100. The result 2L therefore becomes 200L, exactly the same physical quantity in the new coordinate system.

A module is a source component checked against an explicit import and export interface. Separate compilation elaborates each module without inspecting its clients; linking combines the compiled cores after checking that their interfaces agree. The theorem assumes one whole-program unit environment and compares two coherent elaborations of the same source. The type Num[L] records a dimension but not a module’s chosen canonical scale. Separate compilation therefore also requires the export interface to expose the scale map. Two modules with different maps may otherwise elaborate the same coefficient incoherently. A link-time coherence check, or a numeric type indexed by the chosen unit, can enforce this invariant.

The exact boundary

A dimension exponent records how physical units compose. It is not a count of how often a variable is used, a security level, or a logical predicate on a number. The expression L2 says “area” even when the program uses its input once; the dimensionless type Num[1] contains both positive and negative numbers. Those observations prevent the dimension group from being silently reused as a resource or refinement judgment.

A transcendental primitive must consume a dimensionless argument. For example, a conservative extension would give Γe:Num[1]Γlog(e):Num[1]. Then log(3@m) has no derivation because LD1. The core grammar omits transcendental arithmetic so that its coefficient calculations remain exact; the dimension restriction is the part a larger numeric language should retain.

Two nearby numeric conventions also fall outside this calculus. First, every unit conversion above is multiplicative and therefore preserves zero and addition. An absolute-temperature conversion such as cc+27315/100 is affine: it cannot be represented by any scale su, because 0su=0. Temperature differences still fit the multiplicative fragment, but absolute temperatures need a distinct affine quantity interface. Second, powers have a fixed integer exponent. A generic square-root primitive would have to solve ϵ2=d; it is not defined for a dimension whose normalized exponent vector contains an odd coefficient. Accepting such an operation would require an explicit divisibility premise or a richer constrained type, not a silent extension of D-Pow.

The use of integer exponents is a modeling choice. With rational exponents, dimensions form a Q-vector space: square and higher roots of dimension expressions are always available, and Smith divisibility is replaced by ordinary rational rank. That extension models quantities such as amplitude spectral densities, but gives up the integer-exponent lattice ZB and its integral failure certificates.

Finally, Num[1] merges every dimensionless quantity. It cannot distinguish a pure ratio from an angle, cycle count, neper, or decibel. Radians are dimensionless in SI, while logarithmic units encode convention-dependent transforms of dimensionless ratios; preserving those distinctions requires nominal quantity tags in addition to dimensions. This is a deliberate boundary of the calculus, not a claim that the quantities are interchangeable.

Suggested first pass.

Begin with exercise 6.5, then reconstruct the mixed-unifier argument in exercise 6.6.

Exercise 6.5

★☆☆ Extend the source unit environment by kg(1,M), taking kilograms as the canonical source mass unit. Let χ(L)=100, χ(T)=1, and χ(M)=1000. Compute χ(MLT2) and use theorem 6.35 to translate a value 3@kgms2 to coherent gram–centimeter–second coefficients. Verify the result directly from the three base factors.

Exercise 6.6

★★☆ Run munify on the ordered store αNum[δ],αNum[L]. Record the ordinary-variable elimination and the residual dimension equation, then replay the returned substitution against both inputs. For an arbitrary solution R, exhibit a substitution T satisfying R{α,δ}=(ρ;T){α,δ}, where ρ is the returned answer.

Exercise 6.7

★★★ Run the Smith algorithm on δ4ϵ6=L2. Multiply the elementary column matrices to obtain V with [4  6]V=[2  0]. Derive the one-parameter principal solution from z=Vz, verify it by substitution, and explain why replacing the right side by L fails the pivot divisibility test.

Exercise 6.8

★★☆ Assume a proposed unit literal elaborates by q@uaq+bd. Show that the elaboration preserves addition exactly when b=0. Then apply the calculation to Celsius-to-Kelvin conversion and explain why a type of absolute temperatures must be distinguished from a type of temperature differences.

Exercise 6.9

★★★ Practical project.dimension-inferencer Implement the dimension-expression normalizer and the inference delta of definition 6.16 with disjoint supplies, an ordered equation store, and replay of the returned substitution. Use three public entry points: solveDimSystem returns a solved substitution and unused supply or a divisibility certificate; inferW returns the inferred type, composed substitution, generated store, and both unused supplies; evalCore returns a numeral or aritherr. In artifacts/ch6-dimension-inferencer/, run kappa check, kappa test, kappa run, and kappa audit on corpus.kp.

The acceptance fixtures must infer δ.Num[δ]Num[δ2] for square, reduce 100@cm+1@m to the canonical coefficient 2 at dimension L, reject 3@m+2@s, solve and replay δ2ϵ3=L, and reject δ2=L by the Smith divisibility test. Under y:Num[δ], infer the scheme α.αNum[δ] for λz.y: the environment variable δ must not be generalized. After the recursive calls for a binary term, record Γ[S1], τ1[S2], and S1;S2 before invoking the mixed unifier. Ship a check-clean mutation that accepts the odd pivot and show that kappa test rejects it. The bundled corpus checks normalization, simple divisibility, unit conversion, the empty-environment square example, and the mutation oracle. It reports the coupled row δ2ϵ3=L as Unsupported and uses an empty-environment inference shortcut. Completing the project requires the Smith gcd-rebasing branch and environment-sensitive W calls described above.

Search the book

Type to search the local edition.