Documentation

LambdaS.Examples

Λs, running #

Most lines below are #guard assertions that run the checker (and in places the evaluator and the drift analysis) at build time. If any result were different, this file would not compile. The theorems are kernel-checked, and inverseIsIdentity runs in the compiled binary (LambdaS.JacobiChecks).

A note on what the guards do and do not establish. #guard runs infer in Lean's interpreter, so these are tests, not kernel-checked proofs: kernel reduction gets stuck on the Rat instance chain that Mathlib's algebraic hierarchy is built from, which is a known cost of building on it. The correctness guarantee does not come from here: it comes from LambdaS.Typing, where check returns the derivation (so soundness holds by construction) and check_eq is proved in the kernel, saying nothing well-typed is rejected. These examples show the verified checker running.

Five base units; note that three of them measure Length. That is deliberate: it is the configuration a "one named unit per dimension" restriction forbids, and the one conversion factors live in.

Instances For
    @[instance_reducible]
    Equations
    @[instance_reducible]
    Equations
    • One or more equations did not get rendered due to their size.

    The dimensions those units measure.

    Instances For
      @[instance_reducible]
      Equations
      @[instance_reducible]

      The declared dimension of each base unit. Meter, foot, and yard collapse to the same dimension; nothing else does.

      Note that dim lands in DExp Dim 0, a dimension expression, not a single base dimension. That is what lets a derived unit be declared directly at a compound dimension.

      Equations
      • One or more equations did not get rendered due to their size.
      @[reducible, inline]

      The empty dimension context: a closed term has no unit variables in scope.

      Equations
      Instances For
        @[reducible, inline]

        Terms and types of the running example, at the closed scope.

        Equations
        Instances For
          @[reducible, inline]

          The type a closed term is assigned.

          Equations
          Instances For
            @[reducible, inline]

            The type a term is assigned in a non-empty value context.

            Equations
            Instances For
              @[reducible, inline]
              abbrev LambdaS.Examples.bu {k : ℕ} (b : Base) :

              A base unit as a unit expression, at any scope.

              Equations
              Instances For

                Scalars #

                1.3 m: a literal times a unit constant.

                Equations
                Instances For

                  The error that motivates the whole exercise #

                  Adding a length to a duration is a dimension mismatch.

                  Equations
                  Instances For

                    Roots, where ℚ exponents pay for themselves #

                    Kennedy's Λu, like F# before version 4.0, types sqrt : float<'u^2> -> float<'u> over integer exponents, so applying it at a volume requires solving 2·vec(u) = 3 over ℤ. There is no solution, so an integer-exponent system rejects the square root of a volume. Over ℚ the root is total, and this lands at m^(3/2).

                    Spaces #

                    A state space whose components carry different units: position in meters, momentum in kg·m/s. This is the non-uniform case F# cannot express at all, since it parameterizes a type by a single unit.

                    Linear maps #

                    Unit polymorphism #

                    The reason Kennedy's calculus exists, now over spaces, with the dimension bound that lets a polymorphic function still convert.

                    ∀u. τ is not primitive. It is ∀δ. ∀u:δ. τ: a unit variable bounded by a dimension variable. That is what makes it genuinely unbounded, and the guards below check both halves: that δ matches any concrete dimension on instantiation, and that nothing concrete matches δ inside the binder.

                    @[reducible, inline]

                    The bound unit variable, inside one unit binder.

                    Equations
                    Instances For
                      @[reducible, inline]

                      The bound dimension variable, inside one dimension binder.

                      Equations
                      Instances For
                        @[reducible, inline]
                        abbrev LambdaS.Examples.sqrAt (d : DExp Dim 0) (μ : UExp Base 0) :

                        Using it takes two applications: supply the dimension, then the unit.

                        Equations
                        Instances For

                          Addition at any unit, but the same unit on both sides.

                          Equations
                          • One or more equations did not get rendered due to their size.
                          Instances For

                            Polymorphism does not weaken the check. Λδ. Λu:δ. λ(x : Q u). x + 1 is rejected, because u is rigid inside the binder and cannot be 1.

                            Equations
                            Instances For

                              Two distinct unit variables cannot be added either: nested binders really introduce fresh variables rather than shadowing.

                              Equations
                              • One or more equations did not get rendered due to their size.
                              Instances For

                                Conversion under a binder #

                                This is what the dimension bound buys, and what an unbounded quantifier cannot express: a polymorphic function that converts its argument.

                                Λu:Length. λ(x : Q u). convert x u meter: take a length in any unit, return it in meters.

                                Equations
                                • One or more equations did not get rendered due to their size.
                                Instances For

                                  The unbounded quantifier cannot convert. The same body under ∀δ. ∀u:δ. is rejected: dimOf reports the dimension variable δ, which is not the dimension of the meter, so SameDim fails. This is the rejection an unbounded quantifier ought to give, and it is why the bound is a dimension variable rather than the trivial dimension: under the trivial dimension u would be claimed dimensionless, and a conversion from u to a dimensionless unit such as m/ft would wrongly be accepted.

                                  Equations
                                  • One or more equations did not get rendered due to their size.
                                  Instances For

                                    Physics: where the exponents come from #

                                    @[reducible, inline]

                                    G = m³/(kg·s²)

                                    Equations
                                    • One or more equations did not get rendered due to their size.
                                    Instances For

                                      The Planck length, √(ħG/c³). Three constants, three base dimensions, an exponent matrix of rank 3, so by the Pi theorem the combination with dimension Length is unique. The checker confirms the standard formula lands on meters.

                                      Equations
                                      • One or more equations did not get rendered due to their size.
                                      Instances For

                                        Getting the power of c wrong is caught.

                                        Equations
                                        • One or more equations did not get rendered due to their size.
                                        Instances For

                                          Fermion fields have mass dimension 3/2. The Lagrangian carries mass dimension 4 and the kinetic term contributes 2[ψ] + 1, forcing [ψ] = 3/2.

                                          This is the case that matters, and it is not like the Planck length. There the half-powers cancel inside the root: ħG/c³ is already m², so every intermediate has integer exponents and F# types it fine after grouping. A fermion field carries 3/2 standing alone, appearing by itself in every interaction term with nothing to group against. An integer-exponent units system cannot write this type in the fixed mass basis. Rebasing at a square root of mass would integralize it; the modularity problem is that a library chooses its basis before seeing all of its clients' exponent requirements.

                                          Equations
                                          • One or more equations did not get rendered due to their size.
                                          Instances For

                                            The base-measure problem, as a type error #

                                            A probability density over a space whose measure carries μ itself carries μ⁻¹; that is what makes ∫ p dμ dimensionless. So log p is not well-typed, which is the base-measure problem: a density means nothing except relative to the measure it was taken against, and representing a distribution by its density silently discards that measure.

                                            Radul and Alexeev (arXiv:2010.09647) identify exactly this failure in probabilistic programming systems and fix it by library convention. Here the checker rejects it.

                                            @[reducible, inline]

                                            A probability density over a length-parameterized space: m⁻¹.

                                            Equations
                                            Instances For
                                              @[reducible, inline]

                                              A wavefunction is a half-density, at m^(-1/2). Squaring it gives a weight-1 density, which is the normalization condition.

                                              Equations
                                              Instances For

                                                Conversion, and the ambiguity that never arises #

                                                A conversion operator that walks a declared structure has a latent bug: with units nameable in terms of other units, two routes from u to v need not agree. Λs cannot exhibit it. Conversion is a ratio of one valuation (LambdaS.Conversion), so convChain_eq makes path independence a theorem rather than a proof obligation on declarations.

                                                What the checker enforces is the side condition (that the two units measure the same thing), and that is SameDim.

                                                Declarations, and the conflict that cannot be declared away #

                                                unit yard = 3 foot declares a generator and an equation. Three such declarations give two routes from yard to meter, which a converter that walks declarations can follow to different answers. Here the redundant declaration is either arithmetically right or the system has no solution: there is never a choice of route to get wrong.

                                                Base units of equal declared dimension are interchangeable, via dimOf_ofBase rather than decide, since kernel reduction sticks on ℚ's instance chain. The dimension equation is rfl for any two Length units.

                                                unit yard = 0.9144 meter: the redundant declaration, stated correctly.

                                                Equations
                                                Instances For

                                                  unit yard = 0.9 meter: the same declaration, stated wrongly. This is the one that would have made convert route-dependent.

                                                  Equations
                                                  Instances For

                                                    The consistent set forces the redundant factor. Any valuation satisfying all three declarations forces 3 × 0.3048 = 0.9144, so the second route cannot disagree with the first.

                                                    The conflicting set has no valuation at all.

                                                    This is the route-ambiguity bug, decided rather than papered over. A convert that walks a declared structure can walk the wrong way; here the configuration that would force a choice is exactly the configuration with no solution, so it is rejected at declaration time.

                                                    Dimension abbreviations, elaborated #

                                                    Unit declarations constrain; dimension declarations abbreviate, and the only check they need is scoping (DimAbbrev.elabDimDefs, in LambdaS.Declare). The chain below elaborates, with Accel landing at the vector length·time⁻². The cyclic pair Velocity = Length/Time; Length = Velocity/Time is rejected at its second line for rebinding the generator Length, and a forward reference is rejected because an undefined name does not denote.

                                                    Velocity = Length/Time; Length = Velocity/Time: rebinds a generator.

                                                    Equations
                                                    Instances For

                                                      Primary-unit declarations: unit meter : Length; unit second : Time; unit hertz : Frequency with Frequency an abbreviation. Elaborates; the duplicate and the unknown dimension are rejected.

                                                      Equations
                                                      Instances For

                                                        The valuation the declarations determine, and the evaluator using it #

                                                        yard_conflict says the bad set has no valuation; this is the other half, exhibited rather than asserted: the consistent set has one, written down. Its factors then reach the evaluator through evalC_convert_declared: the number the evaluator multiplies by is the number the declaration names, with no route through an informal reading of "3". The theorems below run eval at carrier ℝ, with conv ψyd as the conversion oracle; LambdaS.Algorithms runs the same evaluator at Float with the declared magnitudes transcribed.

                                                        noncomputable def LambdaS.Examples.ψyd :

                                                        The valuation meter = 1, foot = 0.3048, yard = 0.9144 (in log space).

                                                        Equations
                                                        • One or more equations did not get rendered due to their size.
                                                        Instances For

                                                          The consistent set is satisfiable: the counterpart to yard_conflict, with the witness constructed rather than assumed.

                                                          Cycles are constraints, not definitions #

                                                          Declarations carry no order and no acyclicity condition, and need none: each is an equation, the set is a simultaneous system, and a cycle is just a dependency the criterion decides. Nothing can reference an undeclared generator either, since the base units are the parameter B. The benign cycle below is satisfiable, by the same valuation as the straight set; the vicious one forces 3 = 1 and no valuation exists.

                                                          unit foot = 1/3 yard, the converse of dYardFoot: a benign cycle.

                                                          Equations
                                                          Instances For

                                                            A benign cycle is satisfiable: yard = 3 foot and foot = 1/3 yard say the same thing, and the criterion sees a passing dependency, not a loop.

                                                            A vicious cycle is rejected: yard = 3 foot and foot = yard force 3 = 1, so no valuation exists.

                                                            theorem LambdaS.Examples.one_yard_is_three_feet :
                                                            ∃ (n : ℕ), evalC (conv ψyd) n [] ((Tm.ucon yd).convert yd ft) = some (Val.scalar { mag := 3, unit := ft })

                                                            One yard is three feet, on the evaluator. Evaluating (1 yd) in ft at carrier ℝ, with the conversion oracle the declarations determine, multiplies by exactly the declared 3 and lands at ft: evalC_convert_declared, instantiated. The binary runs the same eval at Float (LambdaS.Algorithms).

                                                            theorem LambdaS.Examples.one_yard_in_meters :
                                                            ∃ (n : ℕ), evalC (conv ψyd) n [] ((Tm.ucon yd).convert yd m) = some (Val.scalar { mag := ↑(9144 / 10000), unit := m })

                                                            And directly to meters, by the redundant declaration: the same number the chain through feet produces, which is yard_forced made numeric.

                                                            theorem LambdaS.Examples.one_yard_in_meters_via_feet :
                                                            ∃ (n : ℕ), evalC (conv ψyd) n [] (((Tm.ucon yd).convert yd ft).convert ft m) = some (Val.scalar { mag := ↑(9144 / 10000), unit := m })

                                                            The route through feet lands on the same number. ((1 yd) in ft) in m multiplies by the declared 3 and then by the declared 0.3048, and 3 × 0.3048 = 0.9144 is exactly the magnitude the direct route produces: evalC_convert_declared applied twice, the inner conversion's value read off through Decl.conv_eq_factor.

                                                            theorem LambdaS.Examples.yard_routes_agree :
                                                            ∃ (n₁ : ℕ) (n₂ : ℕ), evalC (conv ψyd) n₁ [] ((Tm.ucon yd).convert yd m) = evalC (conv ψyd) n₂ [] (((Tm.ucon yd).convert yd ft).convert ft m)

                                                            The two routes agree: whatever fuel each needs, the evaluator returns the same value for one yard in meters whether it converts directly or through feet. This is path independence (conv_trans) at the evaluator, for the declared factors.

                                                            Regression: substitution under nested binders #

                                                            Attempting the type-soundness proof turned up a genuine defect in Ty.subst.

                                                            Inside ∀u. τ, de Bruijn index 0 is the bound variable and 1 is the outer one, so substituting for the outer variable must leave the binder alone. The original definition recursed as τ.subst σ.weaken, which substitutes index 0 (the bound variable) and shifts the outer one down into its place. Ty.weaken had the matching defect, inserting the fresh variable at index 0 rather than past the binder.

                                                            Nothing in the examples of the time reached it: single-binder uses were unaffected, and the one nested-binder test then (twoVars) is rejected before substitution runs. The two definitions were also wrong in a way that canceled, so subst_weaken (then the only theorem about them) held regardless.

                                                            It took writing the soundness proof to surface it: the composition lemma for substitution refused to hold, and the reason was that liftU had no counterpart in the quantifier case. The fix was to define subst and weaken as instances of a simultaneous substitution that lifts properly. These guards pin the corrected behavior.

                                                            That is the argument for mechanizing a calculus rather than describing one. The defect is invisible to inspection, invisible to the examples, and invisible to the one property anybody would have thought to state about it.

                                                            @[reducible, inline]

                                                            ∀u. Q v₁: the body mentions the outer variable, not the bound one.

                                                            Equations
                                                            Instances For
                                                              @[reducible, inline]

                                                              ∀u. Q v₀: the body mentions the bound variable.

                                                              Equations
                                                              Instances For

                                                                Algebraic units, in types and in measurements #

                                                                Two expressibility checks worth keeping visible, because a reader of the grammar can miss both. Unit expressions are the free abelian group: a type may be indexed by an algebraic combination of bound unit variables, and a measurement is a literal times a unit constant at any compound unit.

                                                                Λu:Length. Λv:Time. λx : Q (u·v). x: a polymorphic identity at a compound unit built from two distinct bound variables. Inside the two binders, de Bruijn variable 1 is u and 0 is v.

                                                                Equations
                                                                • One or more equations did not get rendered due to their size.
                                                                Instances For

                                                                  5 m/s: a literal times the unit constant at a compound unit. The type is Q (1 · m/s), and the exponent-vector representation makes that the same index as Q (m/s); the #guard compares the vectors.

                                                                  Equations
                                                                  Instances For

                                                                    The drift diagnostic, exercised #

                                                                    The first three programs get three answers. Converting meters to feet and back cancels: unitDrift answers 1, and the result is unit-system independent. Converting one way does not: the drift is m/ft, and the diagnostic names it. And a sum whose branches share a variable carries the branches' shared drift.

                                                                    Addition demands agreeing branch ratios, and x in ft + x in ft has them: both branches carry the drift m/ft.

                                                                    Equations
                                                                    Instances For
                                                                      Equations
                                                                      • One or more equations did not get rendered due to their size.
                                                                      Instances For

                                                                        x in ft + y in ft for distinct measurements x y : Q m is accepted too, with the same drift m/ft. This is the frees-at-one assignment at work: x and y are inputs, inputs rescale ideally, so each contributes the ratio 1 rather than an opaque atom, and the branch ratios are the same exponent vector. An earlier design gave every free variable an atom and declined this program, answering a stronger question than the certified theorems ask: the theorems instantiate the inputs' ratios at 1 (oneTwEnv), and at that instantiation the two branches agree.

                                                                        Equations
                                                                        Instances For
                                                                          Equations
                                                                          • One or more equations did not get rendered due to their size.
                                                                          Instances For

                                                                            What add still declines at first order: a genuine drift disagreement. x in ft + y with x : Q m and y : Q ft converts one branch and not the other, so the branch drifts are m/ft and 1, distinct exponent vectors, and the sum has no uniform drift; indeed the program is not scale-invariant. By Tw.normEq_firstOrder_iff such disagreements are the only declines at add between assigned scalar ratios in a first-order ratio context. Internal applications may introduce redexes; the structural symbolic evaluator handles them without fuel, as in hoSum below. Unknown higher-order input contexts retain the conservative bounded comparison.

                                                                            Equations
                                                                            Instances For
                                                                              Equations
                                                                              • One or more equations did not get rendered due to their size.
                                                                              Instances For

                                                                                A residue of internal abstraction. An abstraction applied inside a first-order program leaves a redex behind: (λf. f x) (λy. y in ft) has the ratio m/ft under every scaling, and unitDrift names it, because deciding triviality normalizes the ratio fully (Tw.nfOne). But twistOf reduces one β-step at construction, and the redex the outer application creates, (λy. ...) 1, survives in the ratio as an app node, which Tw.flat treats as an opaque atom. The ratio as built is not atom-free; its normal form is, and the branch comparison runs on normal forms (Tw.normEq).

                                                                                Equations
                                                                                • One or more equations did not get rendered due to their size.
                                                                                Instances For
                                                                                  Equations
                                                                                  • One or more equations did not get rendered due to their size.
                                                                                  Instances For

                                                                                    Summing hoApp with x in ft, two branches worth m/ft under every scaling, is accepted at that drift: the comparison normalizes both branches first, so the residue is reduced away and two unit expressions are compared. Before the comparison ran on normal forms this sum was declined, an atom against a unit.

                                                                                    Equations
                                                                                    Instances For

                                                                                      Division of a unit by itself is the trivial unit: exponent vectors subtract to zero.

                                                                                      log ((x in ft)/(x in ft)): the argument's conversions cancel, so it is drift-free, and a drift-free value at Q 1 is declaration-independent under every rescaling. Its logarithm is declaration-independent too, and the analysis accepts it: log runs the add-style check against the literal ratio 1 rather than declining unconditionally.

                                                                                      Equations
                                                                                      Instances For
                                                                                        Equations
                                                                                        • One or more equations did not get rendered due to their size.
                                                                                        Instances For

                                                                                          What log still declines: an argument at Q 1 whose ratio genuinely drifts. (x in ft)/y for x : Q m, y : Q ft is dimensionless but carries the drift m/ft, and no ratio describes how its logarithm moves.

                                                                                          Equations
                                                                                          Instances For
                                                                                            Equations
                                                                                            • One or more equations did not get rendered due to their size.
                                                                                            Instances For

                                                                                              β at the ratio level. The left branch wraps x in ft in an identity application, so its ratio arrives as a β-redex; twistOf reduces it on the spot (Tw.appE), the flat form sees the bare exponent vector m/ft rather than an opaque atom, and the sum is accepted with the shared drift. Before the reduction this program was declined for a spelling difference.

                                                                                              Equations
                                                                                              • One or more equations did not get rendered due to their size.
                                                                                              Instances For
                                                                                                Equations
                                                                                                • One or more equations did not get rendered due to their size.
                                                                                                Instances For

                                                                                                  The λ-wrapped kernel: λx:Q m. λy:Q m. (x in ft) + (y in ft). Closed, so unitDrift has no context to pin; unitDriftLam strips the two leading binders, treats x and y as inputs, and reports the kernel's drift, the same verdict addTwoVars receives as an open term: by unitDriftLam_eq_unitDrift the two spellings' verdicts are one computation, and unitDriftLam_spec makes the verdict exact for the applied kernel.

                                                                                                  Equations
                                                                                                  • One or more equations did not get rendered due to their size.
                                                                                                  Instances For
                                                                                                    Equations
                                                                                                    • One or more equations did not get rendered due to their size.
                                                                                                    Instances For

                                                                                                      Branch ratios compare up to the unit algebra, not up to spelling. The two branches below convert the same product of meters to feet, placed differently: the first converts the product once at m·m, the second converts each factor at m. Their ratio terms differ syntactically (the syntactic check Tw.beq rejects exactly this pair), but Tw.normEq flattens both to the unit vector m²/ft² with no argument-drift atoms: the first-order wrapper assigns x and y ratio 1. The result is the drift the branches share.

                                                                                                      Equations
                                                                                                      • One or more equations did not get rendered due to their size.
                                                                                                      Instances For
                                                                                                        Equations
                                                                                                        • One or more equations did not get rendered due to their size.
                                                                                                        Instances For

                                                                                                          The generic caster #

                                                                                                          Under ∀δ. ∀u:δ, conversion out of u is not blocked wholesale: it can target any expression of dimension δ, and in particular another variable bounded by the same δ. The generic caster

                                                                                                          Λδ. Λu:δ. Λv:δ. λx:Q u. convert x u v

                                                                                                          typechecks, at the polymorphic cast type, and instantiating both unit quantifiers at same-dimension ground units yields an ordinary cast. What remains rejected is conversion from u to a concrete unit, since no concrete unit has dimension δ. The caster is a term the two abstraction theorems separate: coherent rescalings give u and v one shared factor and leave it invariant; independent factors move it.

                                                                                                          Λδ. Λu:δ. Λv:δ. λx:Q u. convert x u v.

                                                                                                          Equations
                                                                                                          • One or more equations did not get rendered due to their size.
                                                                                                          Instances For

                                                                                                            Drift through the unit quantifiers #

                                                                                                            The caster's ratio is a family: at bind shape it is indexed by the instantiating unit, and its body's drift is the open exponent vector u/v. The normalizer reads the family at chosen units, so reading it at two fresh unit variables exhibits the open vector itself; and an instantiation is a recorded uapp that twistOf performs on the spot (Tw.uappE).

                                                                                                            Checker plus diagnostic, for the guards below: the drift of a quantity-typed term over Γ, or none where either the checker or the analysis declines.

                                                                                                            Equations
                                                                                                            • One or more equations did not get rendered due to their size.
                                                                                                            Instances For

                                                                                                              The polymorphic round trip: Λδ. Λu:δ. Λv:δ. λx:Q u. (x in v) in u.

                                                                                                              Equations
                                                                                                              • One or more equations did not get rendered due to their size.
                                                                                                              Instances For

                                                                                                                The coherent fundamental theorem, at a rescaling that moves a dimension #

                                                                                                                fundamental quantifies over dimension rescalings Φ. This section instantiates it at a Φ that is not the identity: it multiplies every Length by 2 and fixes Mass and Time. The term is a conversion from meters to feet, so the instantiation exercises the convert case of the theorem, the case that requires coherence.

                                                                                                                A dimension rescaling that doubles Length and fixes Mass and Time. In log coordinates the Length entry is log 2, which is nonzero, so this rescaling moves a dimension.

                                                                                                                Equations
                                                                                                                • One or more equations did not get rendered due to their size.
                                                                                                                Instances For

                                                                                                                  ΦDouble is not the trivial rescaling: it moves the Length dimension.

                                                                                                                  The unit rescaling ΦDouble pulls back to: each base unit scales by the factor of its dimension, so meter, foot, and yard all scale by 2 while kilogram and second are fixed.

                                                                                                                  Equations
                                                                                                                  • One or more equations did not get rendered due to their size.
                                                                                                                  Instances For

                                                                                                                    ψDouble factors through dimension via ΦDouble, by construction: its base field is definitionally the sum Scaling.Factors requires.

                                                                                                                    λ(x : Q m). convert x m ft, closed and parametric: the conversion is the only non-variable subterm, and Tm.Parametric admits convert.

                                                                                                                    Equations
                                                                                                                    Instances For

                                                                                                                      fundamental, instantiated at a rescaling that moves a dimension. The conversion program is related to itself under ΦDouble, which rescales Length by 2. Unfolding RelCo at the arrow type: for inputs related by ψDouble.scale m, the outputs are related by ψDouble.scale ft. The convert case of fundamental carries the content here, since the conversion factor conv V m ft must be invariant under the rescaling, and coherence of ψDouble (every Length unit scales by the same factor 2) is exactly what makes it so.

                                                                                                                      Vector and matrix literals #

                                                                                                                      Until the introduction forms existed, vectors and matrices entered only as free variables: the calculus could consume its data but not construct it. These guards exercise the forms that close the gap: a State vector built one component at a time, matrices built one row at a time, the rejections the rules impose, and the zero-row width story that mnil's annotation exists to tell.

                                                                                                                      @[reducible, inline]

                                                                                                                      The momentum unit of State, kg·m/s.

                                                                                                                      Equations
                                                                                                                      Instances For

                                                                                                                        The State vector as a literal: position 1.3 m consed onto momentum 21 kg·m/s.

                                                                                                                        Equations
                                                                                                                        Instances For

                                                                                                                          Consing a duration where the momentum slot expects kg·m/s builds a vector over a different space, and the eliminations reject it: a State-consuming map applies to the literal above and not to this one.

                                                                                                                          Equations
                                                                                                                          Instances For

                                                                                                                            A map from State to W = [sec] as a literal: one row whose entry i carries sec / State i, which is the rank-one condition the mcons rule checks.

                                                                                                                            Equations
                                                                                                                            • One or more equations did not get rendered due to their size.
                                                                                                                            Instances For

                                                                                                                              A two-row map the other way, one row per component of State.

                                                                                                                              Equations
                                                                                                                              • One or more equations did not get rendered due to their size.
                                                                                                                              Instances For

                                                                                                                                Row extraction #

                                                                                                                                mrow is the elimination form for Lin, dual to mcons as idx is to vcons. Introduction and elimination meet exactly: row 0 of mcons w r M has exactly the type r was checked at. Without it a matrix could be built and applied but never read, so no closed term could name a matrix element, a column, or a transpose.

                                                                                                                                A transpose, at fixed arity. The transpose of a map V → W is the map W* → V* on the dual spaces, whose units are the reciprocals. Here fromTime : Lin W State, so its transpose lives at Lin [1/m, 1/pmom] [1/sec], and the one row of the transpose is the one column of fromTime, assembled entry by entry from row extractions. The mcons rule checks that the entries m/sec and pmom/sec are exactly (1/sec) / (1/m) and (1/sec) / (1/pmom), which is where the dual spaces come from.

                                                                                                                                Equations
                                                                                                                                • One or more equations did not get rendered due to their size.
                                                                                                                                Instances For

                                                                                                                                  Trace, determinant, and inverse of a dimensioned endomorphism #

                                                                                                                                  Hart's endomorphism class, as terms. On Lin State State entry (j,i) carries State j / State i, so the diagonal is dimensionless and so is every permutation product; entry_id_diag and entry_perm_prod state that as unit identities in the map model. The terms below compute the quantities at a fixed size, and the checker assigns them unit 1 from the matrix type alone. The inverse of an endomorphism is again an endomorphism, and the cofactor formula at 2×2 lands there with no annotation beyond the two row units.

                                                                                                                                  The context: one endomorphism of the position-momentum space.

                                                                                                                                  Equations
                                                                                                                                  Instances For

                                                                                                                                    The trace: a sum of two diagonal entries, each dimensionless.

                                                                                                                                    Equations
                                                                                                                                    Instances For

                                                                                                                                      The determinant. Both permutation products are dimensionless, so the subtraction is an addition at equal units.

                                                                                                                                      Equations
                                                                                                                                      • One or more equations did not get rendered due to their size.
                                                                                                                                      Instances For

                                                                                                                                        The inverse by the cofactor formula. Each row is checked at the space mcons demands: row 0 at m / State = [1, s/kg] and row 1 at pmom / State = [kg/s, 1]. Negation is multiplication by -1, since a literal 0 is dimensionless and cannot be subtracted from a s/kg entry.

                                                                                                                                        Equations
                                                                                                                                        • One or more equations did not get rendered due to their size.
                                                                                                                                        Instances For

                                                                                                                                          A literal endomorphism, entries at the units its rows demand: [[2, 1 s/kg], [3 kg/s, 4]], trace 6, determinant 5.

                                                                                                                                          Equations
                                                                                                                                          • One or more equations did not get rendered due to their size.
                                                                                                                                          Instances For

                                                                                                                                            The composite A⁻¹ ∘ A, an endomorphism the evaluator can multiply out.

                                                                                                                                            Equations
                                                                                                                                            Instances For

                                                                                                                                              Evaluate a closed term at Float, with a conversion oracle nothing here consults.

                                                                                                                                              Equations
                                                                                                                                              Instances For

                                                                                                                                                Entry-wise agreement within a floating-point tolerance.

                                                                                                                                                Equations
                                                                                                                                                • One or more equations did not get rendered due to their size.
                                                                                                                                                Instances For

                                                                                                                                                  A⁻¹ ∘ A is the identity. Composition reaches the C dot product, which the interpreter cannot run, so this check executes in the native binary (JacobiChecks), as the sweep's numerical checks do.

                                                                                                                                                  Equations
                                                                                                                                                  • One or more equations did not get rendered due to their size.
                                                                                                                                                  Instances For

                                                                                                                                                    Drift for vectors and matrices #

                                                                                                                                                    The drift of a vector is a vector of drifts, and the drift of a matrix is a matrix of drifts. A literal whose component converts one way is reported with a drift vector naming the component's ratio, not declined; a vector whose drift vector is trivial obeys its type's scaling law component by component (scaleLaw_vec_of_driftFree); idx projects the component's drift back out; and a matrix application carries the add-style agreement condition per output row, across the summed index, so a row whose summands carry genuinely different drifts is declined.

                                                                                                                                                    x : Q m, t : Q s ⊢ ⟨x in ft, t⟩: a vector literal whose first component converts one way and whose second does not.

                                                                                                                                                    Equations
                                                                                                                                                    Instances For
                                                                                                                                                      Equations
                                                                                                                                                      • One or more equations did not get rendered due to their size.
                                                                                                                                                      Instances For

                                                                                                                                                        x : Q m, t : Q s ⊢ ⟨(x in ft) in m, t⟩: the round trip in the first component. Its drift vector is trivial, so scaleLaw_vec_of_driftFree applies: rescaling the arguments moves each component by exactly the factor its type predicts.

                                                                                                                                                        Equations
                                                                                                                                                        • One or more equations did not get rendered due to their size.
                                                                                                                                                        Instances For
                                                                                                                                                          Equations
                                                                                                                                                          • One or more equations did not get rendered due to their size.
                                                                                                                                                          Instances For

                                                                                                                                                            Indexing the drifting component recovers exactly the scalar diagnosis the one-way conversion would get on its own.

                                                                                                                                                            Equations
                                                                                                                                                            Instances For
                                                                                                                                                              @[reducible, inline]

                                                                                                                                                              A context for the matrix-application examples: a length, and a dimensionless entry at exactly the unit ft/ft the rank-one row space demands.

                                                                                                                                                              Equations
                                                                                                                                                              Instances For

                                                                                                                                                                A 1×2 matrix applied to a drifting vector, agreement holding: both argument components carry the same variable through the same conversion, and both row entries are the same variable, so the two products across the sum agree and the output row's drift is their common value.

                                                                                                                                                                Equations
                                                                                                                                                                • One or more equations did not get rendered due to their size.
                                                                                                                                                                Instances For
                                                                                                                                                                  Equations
                                                                                                                                                                  • One or more equations did not get rendered due to their size.
                                                                                                                                                                  Instances For

                                                                                                                                                                    The same shape with distinct measurements in the argument components: the mapp analogue of addTwoVars. Under the frees-at-one assignment both components contribute the ratio 1 through their own variable, so the products across the sum agree at the exponent vector m/ft and the application is accepted; an earlier design gave x and y distinct atoms and declined it.

                                                                                                                                                                    Equations
                                                                                                                                                                    • One or more equations did not get rendered due to their size.
                                                                                                                                                                    Instances For
                                                                                                                                                                      Equations
                                                                                                                                                                      • One or more equations did not get rendered due to their size.
                                                                                                                                                                      Instances For
                                                                                                                                                                        @[reducible, inline]

                                                                                                                                                                        A length, a length in feet, and a dimensionless entry at ft/ft.

                                                                                                                                                                        Equations
                                                                                                                                                                        Instances For

                                                                                                                                                                          What mapp still declines at first order: a genuine drift disagreement across the summed index, the mapp analogue of addMixed. One argument component converts (x in ft, drift m/ft) and the other is already in feet (drift 1), so the row's two products carry distinct exponent vectors and no uniform output drift exists.

                                                                                                                                                                          Equations
                                                                                                                                                                          • One or more equations did not get rendered due to their size.
                                                                                                                                                                          Instances For
                                                                                                                                                                            Equations
                                                                                                                                                                            • One or more equations did not get rendered due to their size.
                                                                                                                                                                            Instances For

                                                                                                                                                                              Case study: a mixed-unit ballistics kernel #

                                                                                                                                                                              The drift diagnostic has so far run on one-line programs. This section runs it on a small straight-line kernel with the shape real conversion bugs have: field data arrives in imperial units, the physics is metric, and the report goes back out in imperial units.

                                                                                                                                                                              Inputs: a distance in feet (variable 0) and a time in seconds (variable 1). The shared pipeline converts the distance to meters, forms the velocity in m/s, and computes the kinetic energy per unit mass v²/2 in m²/s². Four reporting variants, four verdicts, all decided at build time:

                                                                                                                                                                              Every routine typechecks by a #guard on the inferred type, and every drift claim is a #guard on unitDrift, so a wrong claim fails the build.

                                                                                                                                                                              @[reducible, inline]

                                                                                                                                                                              The kernel's input context: a distance in feet and a time in seconds.

                                                                                                                                                                              Equations
                                                                                                                                                                              Instances For

                                                                                                                                                                                Meter and foot share a dimension, so velocity squared does too: the side condition the energy conversions below discharge, proved by the homomorphism laws for dimOf rather than by decide.

                                                                                                                                                                                The shared pipeline #

                                                                                                                                                                                Real code shares subterms, so the variants do too: one converted distance, one metric velocity, one imperial velocity, each with its derivation.

                                                                                                                                                                                Metric velocity: the converted distance over the raw time input.

                                                                                                                                                                                Equations
                                                                                                                                                                                Instances For

                                                                                                                                                                                  Imperial velocity: the raw inputs, no conversion.

                                                                                                                                                                                  Equations
                                                                                                                                                                                  Instances For
                                                                                                                                                                                    @[reducible, inline]

                                                                                                                                                                                    The one-way drift both drifted variants share: one foot-to-meter conversion, squared through v².

                                                                                                                                                                                    Equations
                                                                                                                                                                                    Instances For

                                                                                                                                                                                      Variant 1: convert in, compute, convert out #

                                                                                                                                                                                      (1/2) · ((velM · velM) in ft²/s²): metric energy, reported imperial. The ft → m conversion inside velM enters the ratio twice through the square; the output conversion contributes m²/ft² and cancels it exactly.

                                                                                                                                                                                      Equations
                                                                                                                                                                                      • One or more equations did not get rendered due to their size.
                                                                                                                                                                                      Instances For
                                                                                                                                                                                        Equations
                                                                                                                                                                                        • One or more equations did not get rendered due to their size.
                                                                                                                                                                                        Instances For

                                                                                                                                                                                          Variant 2: convert in, report metric #

                                                                                                                                                                                          Variant 3: the same quantity, two ways, in one sum #

                                                                                                                                                                                          (1/2) · (velM·velM + ((velF·velF) in m²/s²)): the left branch converts the input then squares, the right squares the raw imperial velocity then converts once at ft²/s². Averaging the two would divide by a further literal; adding them keeps the branch comparison the interesting step.

                                                                                                                                                                                          Equations
                                                                                                                                                                                          • One or more equations did not get rendered due to their size.
                                                                                                                                                                                          Instances For
                                                                                                                                                                                            Equations
                                                                                                                                                                                            • One or more equations did not get rendered due to their size.
                                                                                                                                                                                            Instances For

                                                                                                                                                                                              Variant 4: the rooted variant, followed through the root #

                                                                                                                                                                                              √(2 · kernelOneWay): the speed recovered from the energy. Well-typed at m/s (rational powers are total over ℚ exponents), and inside the analysis: Tw.qpow lifts the energy's drift to the power.

                                                                                                                                                                                              Equations
                                                                                                                                                                                              Instances For

                                                                                                                                                                                                A Jacobi rotation, and what the units force #

                                                                                                                                                                                                The reason ifle was added. Section 9 of the paper classifies dimensioned maps, and svd_entry_const says every entry of a map between uniform spaces carries one unit, which is what sorting singular values requires. That is a claim about types; this section runs an actual kernel against it.

                                                                                                                                                                                                The setting is the symmetric eigenvalue problem on Hart's fourth class, the dimensionally symmetric maps A : V ⊸ dual V, here on a uniform V, so every entry carries 1 / (V j * V i) and, uniformly, m⁻². A Jacobi sweep annihilates the off-diagonal entry by a rotation whose angle is computed from the entries themselves.

                                                                                                                                                                                                A uniform two-component space.

                                                                                                                                                                                                Equations
                                                                                                                                                                                                Instances For

                                                                                                                                                                                                  The context the kernel runs in: one symmetric matrix.

                                                                                                                                                                                                  Equations
                                                                                                                                                                                                  Instances For

                                                                                                                                                                                                    The tangent parameter of the rotation angle.

                                                                                                                                                                                                    Every entry carries m⁻², so the difference is legal and the ratio is dimensionless. The rotation is forced to be a pure number, and it is the uniformity of the space that forces it: on a non-uniform space the numerator below does not typecheck.

                                                                                                                                                                                                    Equations
                                                                                                                                                                                                    Instances For

                                                                                                                                                                                                      Absolute value, expressed using the existing comparison and arithmetic forms. The comparison is between quantities at the same unit and names no unit constant.

                                                                                                                                                                                                      Equations
                                                                                                                                                                                                      Instances For

                                                                                                                                                                                                        The magnitude of the off-diagonal entry.

                                                                                                                                                                                                        Equations
                                                                                                                                                                                                        Instances For

                                                                                                                                                                                                          A nonnegative relative scale: the larger diagonal magnitude.

                                                                                                                                                                                                          Equations
                                                                                                                                                                                                          • One or more equations did not get rendered due to their size.
                                                                                                                                                                                                          Instances For

                                                                                                                                                                                                            t = sign(τ) / (|τ| + √(1 + τ²)) when the off-diagonal is nonzero. An already diagonal input uses t = 0, before evaluating the division in tau. The zero in the comparison is obtained by multiplying the entry by zero, so it carries the entry's unit without introducing a unit constant.

                                                                                                                                                                                                            Equations
                                                                                                                                                                                                            • One or more equations did not get rendered due to their size.
                                                                                                                                                                                                            Instances For

                                                                                                                                                                                                              The rotation itself, an endomorphism of the uniform space. Its entries carry V j / V i = 1, so a rotation is a matrix of plain numbers, which is entry_id_diag and entry_perm_prod seen from the term side. Its signs are [[c, s], [-s, c]], matching tau = (d - a)/(2b) in the congruence Rᵀ A R.

                                                                                                                                                                                                              Equations
                                                                                                                                                                                                              • One or more equations did not get rendered due to their size.
                                                                                                                                                                                                              Instances For

                                                                                                                                                                                                                Its transpose, assembled column by column with mrow. The rotation is orthogonal, so this is also its inverse, and it lands at the dual spaces.

                                                                                                                                                                                                                Equations
                                                                                                                                                                                                                • One or more equations did not get rendered due to their size.
                                                                                                                                                                                                                Instances For

                                                                                                                                                                                                                  One Jacobi sweep, the congruence Rᵀ A R. It needs both extensions at once: mrow to build the transpose and ifle to choose the angle. The type is preserved exactly, so sweeps compose.

                                                                                                                                                                                                                  Equations
                                                                                                                                                                                                                  Instances For

                                                                                                                                                                                                                    What the units refuse #

                                                                                                                                                                                                                    The rotation algebra above is not merely typeable on a uniform space; it is typeable only there. On a non-uniform space the two diagonal entries carry different units, so the numerator of tau is an addition at unequal units and the term is rejected before any question of correctness arises. Hart's uniformity condition is visible here as a typing constraint of this particular Jacobi kernel. svd_entry_const supplies the unit identity; the checker guard under ΓN below demonstrates the rejection. No typed general SVD algorithm is mechanized.

                                                                                                                                                                                                                    What the units say about the stopping test #

                                                                                                                                                                                                                    A convergence test compares the off-diagonal magnitude to a tolerance, and the tolerance must carry the entries' unit. Both forms below typecheck; parametricity distinguishes how their tolerances are supplied.

                                                                                                                                                                                                                    A relative tolerance scales a quantity already in hand by a dimensionless factor. It names no unit, so it stays inside the parametric fragment and the paper's Theorem 5.1 (fundamental_free) applies to the kernel.

                                                                                                                                                                                                                    The fixed absolute tolerance below is written using a named unit constant ucon, which Tm.Parametric excludes. The kernel still typechecks and runs, but the abstraction theorem no longer applies. An absolute tolerance passed as an input could remain parametric and would rescale with the inputs; absolute tolerances are not excluded in general.

                                                                                                                                                                                                                    One sweep, skipped (the input returned unchanged) when the off-diagonal magnitude is at most 1e-9 times the larger diagonal magnitude.

                                                                                                                                                                                                                    Equations
                                                                                                                                                                                                                    Instances For

                                                                                                                                                                                                                      The same test against the fixed tolerance 1e-9 m⁻², written with the unit constant ucon (1/m/m).

                                                                                                                                                                                                                      Equations
                                                                                                                                                                                                                      • One or more equations did not get rendered due to their size.
                                                                                                                                                                                                                      Instances For

                                                                                                                                                                                                                        The diagnostic at the sweep #

                                                                                                                                                                                                                        unitDriftGen takes an arbitrary context and a .lin result, so it applies to the kernel exactly as written, matrix argument and matrix result. This is the guard that says so.

                                                                                                                                                                                                                        What the experiment checks #

                                                                                                                                                                                                                        unitDriftGen accepts an arbitrary context and a matrix result. The guard above assigns the sweep ratio 1 at every entry; scaleLaw_lin_of_driftFree_gen connects this result to the real scaling law. The non-uniform typing rejection and the two tolerance proofs test separate parts of the unit discipline.

                                                                                                                                                                                                                        LambdaS.JacobiChecks executes these terms in the native binary, including the matrix products that reach the C dot-product implementation. It checks annihilation of both off-diagonal entries, symmetry, trace and determinant, and stopping decisions for both signs. These numerical checks are separate from the typing and drift guards. They cover finite test matrices, not a floating-point correctness theorem for all inputs.

                                                                                                                                                                                                                        The kernel restated over scalar arguments #

                                                                                                                                                                                                                        An earlier drift diagnostic accepted only scalar contexts, and this restatement was the workaround: pass the entries rather than the matrix, so that the context is a scalarCtx. unitDriftGen has since removed the need for it. It stays as a typing check over a scalar context with a matrix result. It predates the sign and zero-guard fixes to rot and tanRot: rotS is [[c, -s], [s, c]] and tanS has no zero guard, so it is typechecked only, never run.

                                                                                                                                                                                                                        The entry unit of a symmetric matrix on the uniform space.

                                                                                                                                                                                                                        Equations
                                                                                                                                                                                                                        Instances For

                                                                                                                                                                                                                          The matrix assembled from them, symmetric by construction.

                                                                                                                                                                                                                          Equations
                                                                                                                                                                                                                          • One or more equations did not get rendered due to their size.
                                                                                                                                                                                                                          Instances For
                                                                                                                                                                                                                            Equations
                                                                                                                                                                                                                            • One or more equations did not get rendered due to their size.
                                                                                                                                                                                                                            Instances For
                                                                                                                                                                                                                              Equations
                                                                                                                                                                                                                              • One or more equations did not get rendered due to their size.
                                                                                                                                                                                                                              Instances For
                                                                                                                                                                                                                                Equations
                                                                                                                                                                                                                                • One or more equations did not get rendered due to their size.
                                                                                                                                                                                                                                Instances For