Conversion, and why paths cannot disagree #
Λs has a conversion operator (convert, a core term constructor), and
conversion is the place to be careful: with units nameable and definable in terms of combinations of other
units, a system that defines conversion by walking a declared structure can
offer more than one route between two units, with no guarantee the routes
agree.
This file answers that. Conversion is not a path at all; it is a ratio of
valuations, and the object that supplies the valuations already exists:
Scaling. A scaling assigns a positive magnitude to every base unit and extends
to a homomorphism, which is exactly what "reduce every unit to a canonical
value" means in the specification of Fortress, a language whose standard
library carried units of measure.
Once conversion is a ratio, path independence is not a condition to check but a
theorem: convChain_eq says any chain of intermediate conversions collapses to
the direct one, because the intermediate factors telescope. The multiple-paths
problem does not arise, and there is nothing an implementation could get wrong.
The contrast worth recording #
There is a real alternative, and it is the one a unit-conversion programming
assignment (Rice's Comp 311, Fall 2016)
adopts: restrict compound units to at most one named unit per dimension, so
that lining up two compounds has a unique pairing. That works, and it kills the
ambiguity, but it buys uniqueness by shrinking the algebra. Under it
meter / foot is illegal, because both are units of Length; yet that is exactly
a conversion factor, dimensionless, and worth naming.
The exponent-vector representation needs no such restriction. meter and foot
are distinct generators that happen to share a dimension, meter * foot is a
perfectly good vector, and no pairing question ever arises because a vector's
components are already indexed.
The conversion factor from u to v, relative to a valuation.
A valuation is a Scaling: it fixes what each base unit is worth, and extends
to a homomorphism on all units. The factor is then just the ratio.
Equations
- LambdaS.conv ψ u v = ψ.scale u / ψ.scale v
Instances For
The factor along a chain of intermediate units.
Equations
- LambdaS.convChain ψ x✝¹ [] x✝ = LambdaS.conv ψ x✝¹ x✝
- LambdaS.convChain ψ x✝¹ (w :: ws) x✝ = LambdaS.conv ψ x✝¹ w * LambdaS.convChain ψ w ws x✝
Instances For
Path independence. Any chain of intermediate conversions from u to
v gives exactly the direct factor.
This is the theorem the multiple-paths problem asks for. It holds because the factors are ratios of a single valuation, so intermediates telescope, not because anyone checked the declarations for consistency. There is no route by which two paths could disagree.
Conversion preserves the quantity. A measurement ⟨m, u⟩ converted into
unit v denotes the same physical quantity: its interpretation under the
valuation is unchanged.
This is the correctness statement for an in operator, and it is what the
Comp 311 assignment needs of its def in(v: PhysicalUnit) and never states.
Rescaling the valuation multiplies a conversion factor by the ratio of the two units' scale factors. The engine of every coherence result: the factor is almost invariant, off by exactly the amount coherence sets to one.
Dimensions #
dimOf lives in LambdaS.Syntax, since the typing rule for convert needs it.
These are the homomorphism laws the design requires of it: dimension is a group
homomorphism from units to dimensions, which is what makes "same dimension" an
equivalence compatible with the algebra.
Interchangeable units have a dimensionless ratio, which is why their conversion factor is a pure number and can itself be named as a unit.
Under the "one named unit per dimension" restriction this ratio is not even
expressible, since u and v would be two units of one dimension in a single
compound.
A linear extension lemma #
The classical fact both this file and LambdaS.Declare consume: a value
assignment on a finite family extends to a linear map exactly when it respects
the family's linear dependencies.
Prescribed values extend to a linear map when dependencies are
respected. Given finite families r in M and v in V over a field K,
a single linear map sends each r i to v i exactly when every K-linear
dependency among the r i also annihilates the corresponding combination of
the v i. This is the extension step behind Scaling.Coherent.factors in this
file and dependency_sufficient in LambdaS.Declare: the value assignment
factors through the span of the family and then extends to the whole space.
Coherence: which scalings are physically meaningful #
Parametricity quantifies over all scalings, including ones that scale
meter and foot independently. That is physical nonsense (rescale the meter
and the foot must follow), but it is exactly the freedom that lets Λs treat
same-dimension units as independent generators, and so avoid restricting
compound units to one named unit per dimension.
The physically meaningful scalings are those that factor through dimension,
and they are precisely the ones that leave conversion factors alone. This is the
bridge between the two roles a Scaling plays: fixed declared data on the one
hand, quantified-over transformation on the other.
It is also the exact price of convert. A parametric term without convert is
scale-invariant for every scaling: that is fundamental_free, and it is what
the Pi theorem consumes. A term with convert is scale-invariant for the
coherent ones, and conv_invariant_of_coherent is the lemma that discharges its
case. Nothing else in Λs can observe a unit, so nothing else pays.
A scaling is coherent for Δ when interchangeable units scale alike;
that is, when it factors through dim.
Equations
- LambdaS.Scaling.Coherent Δ ψ = ∀ (u v : LambdaS.UExp B k), LambdaS.SameDim Δ u v → ψ.scale u = ψ.scale v
Instances For
Conversion factors are invariant under coherent rescaling.
Change the unit system by any scaling that respects dimensions and every
conversion factor is unchanged: 1 m = 3.28 ft whatever reference you measure
against.
ψ factors through dimension via the dimension scaling Φ.
This is Coherent with its witness named, and split into the two facts that
determine it: what each base unit is worth, and what each unit variable is worth.
Coherence says interchangeable units scale alike, which is precisely the
statement that the scaling is pulled back from one on dimensions.
Naming the dimension scaling is what makes unit abstraction tractable. Under
Λu:δ the factor the bound unit must receive is then not merely constrained to
some coherent value; it is determined, namely Φ δ. A coherent rescaling is
a rescaling of dimensions, and unit abstraction has no freedom left.
A base unit scales by its dimension's factor.
A unit variable scales by its declared dimension's factor.
Instances For
Factoring is pointwise, so it extends to every unit expression. The
content is that logScale and dimOf are both linear, so this is a change in
summation order rather than an induction.
Factoring survives a unit binder, at the factor the bound dimension dictates. There is no choice to make, which is the whole point.
Factoring survives a dimension binder, at whatever the new dimension is
worth: dimension abstraction is unconstrained, which is what makes ∀δ. ∀u:δ
genuinely unbounded.
Every coherent scaling factors through dimension. This is the converse
of Scaling.Factors.coherent, and together they give the equivalence the
paper's introduction asserts when it defines coherence as inheriting factors
from dimensions.
The proof is ℚ-linear algebra with values in ℝ. Each generator (base unit or
unit variable) has a dimension exponent vector and a log factor. A rational
dependency among the vectors assembles a dimensionless unit expression, which
coherence sends to the scale of 1, so the corresponding combination of log
factors vanishes. exists_linearMap_of_dependencies then extends the
assignment to a ℚ-linear functional on the whole dimension space, and reading
that functional on the standard basis gives the dimension scaling.
Coherence is factoring through dimension. A scaling respects interchangeability exactly when it is pulled back from some scaling of dimensions. The paper defines coherence by the right-hand side; this equivalence shows the two readings agree.