Move pair P into three-dimensional space, seen from two reference frames: the lab, and a cart moving at constant velocity relative to it. Positions, displacements and distances get distinct ISO 80000-3 kinds, so adding a position to a displacement fails to type-check. The A–B separation is an IndividualQuantity about the pair it belongs to, so pair P's separation cannot be used where pair Q's is expected. Each frame conversion accepts one kind of vector: kGeometricTransport converts displacements and kBoostTransport converts velocities, so passing a displacement to kBoostTransport fails to type-check.
Adding a position to a displacement fails to type-check, and so does adding a distance to the length of a displacement: there is no HAdd instance for either pair of kinds (refused) HCP.L4_OutOfTheLine#points_vectors_and_distances.
Pair P's A–B separation is an IndividualQuantity of kind distance about P, and pair Q's separation supplied where P's is expected fails with a type mismatch (refused) HCP.L4_OutOfTheLine#whose_distance.
The distance between two points equals the length of the displacement between them (theorem) HCP.L4_OutOfTheLine#distance_is_length.
kBoostTransport rejects a displacement with a type mismatch, and adding a velocity to a force fails to type-check (refused) HCP.L4_OutOfTheLine#kinded_frames.
Converting P's displacement from frame F to frame G with kGeometricTransport gives the displacement that G computes from its own coordinates (theorem) HCP.L4_OutOfTheLine#kinded_frames.
The displacement of the cart's origin between times t₁ and t₂ equals the elapsed time times the cart's velocity (theorem) HCP.L4_OutOfTheLine#observer_motion.
Bearer erased: pair P's A–B separation used where pair Q's is meant (HCP.L4_OutOfTheLine#whose_distance).
Observer left implicit: with PhysLib's single vector type, the geometric, boost and origin-shift conversions all accept the same vector; with kinded vectors, each conversion accepts only the kind it is correct for (HCP.L4_OutOfTheLine#bare_frames, HCP.L4_OutOfTheLine#kinded_frames).
Point/vector confusion: a position added to a displacement, or a distance added to the length of a displacement (HCP.L4_OutOfTheLine#points_vectors_and_distances).
You are a PhysLib contributor: a physicist who writes Lean in PhysLib. You know Lean and
PhysLib and trust Dimension and WithDim; L0–L3 have established kinds, bearers,
composition, and body- and lab-frame angular velocity.
The wobble throws body A's centre of mass off the line, and a second observer on a moving cart sees the pair differently. What must the model now say about where things are, and for whom? L4 moves the two centres of mass into Space 3, distinguishes points from vectors and distances, and states the observer whose frame supplies a vector's context. One name is one system: records under it are states at different times, configurations, or rival estimates; comparing them is the point. Distinct names are distinct systems. Pair P's separation has one bearer across its states, while pair Q has a different bearer. The lab frame F and cart frame G are explicit observers.
Bearer erased.distanceQ cannot distinguish the A–B separation of pair P from that of pair Q; the typed cross-pair refusal is pinned at HCP.L4_OutOfTheLine#whose_distance.
Observer left implicit. Bare vectors accept geometric, boost, and origin-shift transport even though only one law is right for each vector kind; HCP.L4_OutOfTheLine#bare_frames shows the wrong accepted forms and HCP.L4_OutOfTheLine#kinded_frames pins the role-specific refusals.
The wobble throws body A's centre of mass off the line, and a second observer on a moving cart sees the pair differently. What must the model now say about where things are, and for whom?
The pair's centres become points in Space 3; lab F and cart G are named frames.
Position vector, displacement, pair distance, and velocity per frame.
Pair P's distance can be confused with pair Q's, and bare frame vectors accept transport laws that are wrong for the vector's role.
Space Stages 0–4.
The remaining one-dimensional, one-observer assumption is gone. The no-dissipation
assumption remains for L5.
Put the two centres in a PairState3; read position, displacement, and distance, then try the two kind collisions.
points_vectors_and_distances
Position and displacement are distinct vector kinds; distance and the length of displacement are distinct scalar kinds, even where magnitudes agree. HCP's body and separation bearers retain nominal identity.
2
Attach the distance to the named pair, compare two states, and mix P with Q.
whose_distance
distance admits DifferenceKind.ofScale; same-name states have a typed change whose magnitude reads their own centres, while Q's separation cannot be added to P's.
3
Relate distance to displacement length and apply the triangle inequality to state points.
distance_is_length
distanceQ_eq_lengthOf_displacementQ and distanceQ_triangle operate directly on the pair state's centres.
4
Feed one state-derived bare frame vector to all three upstream transports and add the cart's origin velocity.
bare_frames
Both terms compile, but are physically wrong when the vector's role is displacement: bare F.Vector cannot select a transport law or distinguish displacement from velocity.
5
Use KVector for displacement and velocity; try the wrong boost and velocity-plus-force.
kinded_frames
Frame components enter through each frame's own dispEquiv; the observer-independence theorem verifies geometric transport. Boost-on-displacement and velocity-plus-force are pinned refusals. Average velocity is computed from two same-pair states and an elapsed duration.
6
State the cart-origin displacement law and try adding its frame velocity to the pair displacement.
observer_motion
origin_displacement_eq makes observer motion an attribute of the cart frame; the kinded displacement-plus-velocity sum is refused.
7
Map Space Stages 0–4 and exercise Stage 3's operator table.
adoption_ladder
spanArea and its magnitude law are accepted on a displacement from the state and a probe point; area × area is refused. Stage 4's boundary and API-map audits are the final rung.
1. Points, vectors, and distances.PairState3 π stores this state's centre-of-mass
points. BodyOf π keeps a body's nominal pair identity, while SeparationOf π names
the pair's A–B separation. The upstream positionQ, displacementQ, and distanceQ
are applied to the state fields. Position plus displacement and distance plus the
length of that displacement are both pinned refusals:
/--
One pair name is one system. Records under that name are its states, configurations, or
rival estimates; comparing them is the point. Distinct names are distinct systems.
-/inductivePairId|P|QderivingDecidableEq,ReprinductiveBody|A|BderivingDecidableEq,ReprstructurePairState3(π:PairId)wherecom:Body→Space3structureBodyOf(π:PairId)wherebody:BodyderivingDecidableEq,ReprstructureSeparationOf(π:PairId)wherederivingDecidableEq,ReprdefbodyS:SortOfSystem:=⟨"body centre"⟩defseparationS:SortOfSystem:=⟨"pair separation"⟩instance{π:PairId}:Sorted(BodyOfπ):=⟨fun_=>bodyS⟩instance{π:PairId}:Designated(BodyOfπ)wheredesignation|⟨.A⟩=>⟨"body A"⟩|⟨.B⟩=>⟨"body B"⟩designation_inj{xy}h:=π:PairIdx:BodyOfπy:BodyOfπh:(matchxwith|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=matchywith|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ x=yπ:PairIdy:BodyOfπx:Bodyh:(match{body:=x}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=matchywith|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ {body:=x}=yπ:PairIdx:Bodyy:Bodyh:(match{body:=x}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=match{body:=y}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ {body:=x}={body:=y}π:PairIdy:Bodyh:(match{body:=Body.A}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=match{body:=y}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ {body:=Body.A}={body:=y}π:PairIdy:Bodyh:(match{body:=Body.B}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=match{body:=y}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ {body:=Body.B}={body:=y}π:PairIdy:Bodyh:(match{body:=Body.A}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=match{body:=y}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ {body:=Body.A}={body:=y}π:PairIdy:Bodyh:(match{body:=Body.B}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=match{body:=y}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ {body:=Body.B}={body:=y}π:PairIdh:(match{body:=Body.B}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=match{body:=Body.A}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ {body:=Body.B}={body:=Body.A}π:PairIdh:(match{body:=Body.B}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=match{body:=Body.B}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ {body:=Body.B}={body:=Body.B}π:PairIdh:(match{body:=Body.A}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=match{body:=Body.A}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ {body:=Body.A}={body:=Body.A}π:PairIdh:(match{body:=Body.A}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=match{body:=Body.B}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ {body:=Body.A}={body:=Body.B}π:PairIdh:(match{body:=Body.B}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=match{body:=Body.A}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ {body:=Body.B}={body:=Body.A}π:PairIdh:(match{body:=Body.B}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=match{body:=Body.B}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ {body:=Body.B}={body:=Body.B}first|All goals completed! 🐙|exactabsurd(System.mk.injh)(π:PairIdh:(match{body:=Body.B}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"})=match{body:=Body.A}with|{body:=Body.A}=>{id:="body A"}|{body:=Body.B}=>{id:="body B"}⊢ ¬"body B"="body A"All goals completed! 🐙)instance{π:PairId}:Sorted(SeparationOfπ):=⟨fun_=>separationS⟩instance{π:PairId}:Designated(SeparationOfπ)wheredesignation_:=⟨"A–B separation"⟩designation_inj{xy}_:=π:PairIdx:SeparationOfπy:SeparationOfπx✝:{id:="A–B separation"}={id:="A–B separation"}⊢ x=yπ:PairIdy:SeparationOfπx✝:{id:="A–B separation"}={id:="A–B separation"}⊢ {}=y;π:PairIdx✝:{id:="A–B separation"}={id:="A–B separation"}⊢ {}={};All goals completed! 🐙defbodyPositionOf{π:PairId}(s:PairState3π)(b:BodyOfπ):IndividualQuantitybForPhysLib.Kinds.Space.positionVector(EuclideanSpaceℝ(Fin3)):=⟨(ForPhysLib.Kinded.Space.positionQ(s.comb.body)).magnitude⟩defpairDisplacementOf{π:PairId}(s:PairState3π):IndividualQuantity(⟨⟩:SeparationOfπ)ForPhysLib.Kinds.Space.displacement(EuclideanSpaceℝ(Fin3)):=⟨(ForPhysLib.Kinded.Space.displacementQ(s.com.A)(s.com.B)).magnitude⟩-- Point vs vector: Constructs body A's location as a bearer-free `Quantity positionVector`; its type records position kind, not pair P versus Q.example(s:PairState3.P):QuantityForPhysLib.Kinds.Space.positionVector(EuclideanSpaceℝ(Fin3)):=ForPhysLib.Kinded.Space.positionQ(s.com.A)-- Point vs vector: Constructs pair P's A-to-B difference as a bearer-free `Quantity displacement`; its type cannot distinguish pair P from Q.example(s:PairState3.P):QuantityForPhysLib.Kinds.Space.displacement(EuclideanSpaceℝ(Fin3)):=ForPhysLib.Kinded.Space.displacementQ(s.com.A)(s.com.B)-- Point vs vector: Constructs pair P's scalar separation as a bearer-free `Quantity distance`; its type separates distance from displacement and length, not P from Q.example(s:PairState3.P):QuantityForPhysLib.Kinds.Space.distanceℝ:=ForPhysLib.Kinded.Space.distanceQ(s.com.A)(s.com.B)-- Point vs vector: Refused: no HAdd instance combines positionVector and displacement; ordinary addition would conflate a point with its offset instead of translating it./--
error: failed to synthesize instance of type class
HAdd (Quantity positionVector (EuclideanSpace ℝ (Fin 3))) (Quantity displacement (EuclideanSpace ℝ (Fin 3))) ?m.10
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
-/#guard_msgs(whitespace:=lax)inexample(s:PairState3.P):=ForPhysLib.Kinded.Space.positionQ(s.com.A)+ForPhysLib.Kinded.Space.displacementQ(s.com.A)(s.com.B)-- Kind vs dimension: Refused: no HAdd instance combines distance and length, preventing a sum of distinct scalar kinds despite their shared length dimension./--
error: failed to synthesize instance of type class
HAdd (Quantity distance ℝ) (Quantity length ℝ) ?m.12
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
-/#guard_msgs(whitespace:=lax)inexample(s:PairState3.P):=ForPhysLib.Kinded.Space.distanceQ(s.com.A)(s.com.B)+ForPhysLib.Kinded.Space.lengthOf(ForPhysLib.Kinded.Space.displacementQ(s.com.A)(s.com.B))
2. Whose distance.distanceQ returns a Quantity and so erases the HCP pair
bearer. separationOf puts that same distance on SeparationOf π. Distance is a
ratio-scale length species, so DifferenceKind.ofScale applies: two records under P
can express a change in separation, while Q's pair bearer does not unify with P's.
defseparationOf{π:PairId}(s:PairState3π):IndividualQuantity(⟨⟩:SeparationOfπ)ForPhysLib.Kinds.Space.distanceℝ:=⟨(ForPhysLib.Kinded.Space.distanceQ(s.com.A)(s.com.B)).magnitude⟩/-- Bearer safety: Proves that pair P's indexed separation magnitude is the distance between body A's and body B's centres of mass. -/lemmaseparationOf_magnitude{π:PairId}(s:PairState3π):(separationOfs).magnitude=dist(s.com.A)(s.com.B):=rfl-- Distance is ratio-scale in ISO 80000-3, so its difference is licensed.-- Composition law: Constructs a DifferenceKind for distance from its ratio scale, licensing a change between states of pair P.example:DifferenceKindForPhysLib.Kinds.Space.distance:=DifferenceKind.ofScaledefseparationChange(earlierlater:PairState3.P):IndividualQuantity(⟨⟩:SeparationOf.P)ForPhysLib.Kinds.Space.distanceℝ:=IndividualQuantity.addDifferenceKind.ofScale(separationOflater)(-(separationOfearlier))/-- Same-name records: Proves that pair P's separation-change magnitude is later A–B distance minus earlier A–B distance. -/lemmaseparationChange_magnitude(earlierlater:PairState3.P):(separationChangeearlierlater).magnitude=dist(later.com.A)(later.com.B)-dist(earlier.com.A)(earlier.com.B):=earlier:PairState3PairId.Plater:PairState3PairId.P⊢ (separationChangeearlierlater).magnitude=dist(later.comBody.A)(later.comBody.B)-dist(earlier.comBody.A)(earlier.comBody.B)earlier:PairState3PairId.Plater:PairState3PairId.P⊢ Carrier.add(dist(later.comBody.A)(later.comBody.B))(-dist(earlier.comBody.A)(earlier.comBody.B))=dist(later.comBody.A)(later.comBody.B)-dist(earlier.comBody.A)(earlier.comBody.B)earlier:PairState3PairId.Plater:PairState3PairId.P⊢ dist(later.comBody.A)(later.comBody.B)+-dist(earlier.comBody.A)(earlier.comBody.B)=dist(later.comBody.A)(later.comBody.B)-dist(earlier.comBody.A)(earlier.comBody.B)All goals completed! 🐙-- Bearer safety: Refused: type mismatch between pair P's and pair Q's SeparationOf bearers; this prevents treating distinct pairs as one distance history./--
error: Application type mismatch: The argument
qDistance
has type
IndividualQuantity (@SeparationOf.mk PairId.Q) distance ℝ
but is expected to have type
IndividualQuantity (@SeparationOf.mk PairId.P) distance ℝ
in the application
IndividualQuantity.add ⋯ (separationOf p) qDistance
-/#guard_msgs(whitespace:=lax)inexample(p:PairState3.P)(q:PairState3.Q):=letqDistance:IndividualQuantity(⟨⟩:SeparationOf.Q)ForPhysLib.Kinds.Space.distanceℝ:=separationOfqIndividualQuantity.addDifferenceKind.ofScale(separationOfp)qDistance
3. Distance is displacement length. These laws are applied to the state’s own A and B
centres. The magnitudes agree, but the kinds remain distinct; the triangle law is another
statement over the points carried by one PairState3.
-- Point vs vector: Proves that pair P's A–B distance equals the length of its displacement; distance is the norm of the connecting vector.example(s:PairState3.P):(ForPhysLib.Kinded.Space.distanceQ(s.com.A)(s.com.B)).magnitude=(ForPhysLib.Kinded.Space.lengthOf(ForPhysLib.Kinded.Space.displacementQ(s.com.A)(s.com.B))).magnitude:=ForPhysLib.Kinded.Space.distanceQ_eq_lengthOf_displacementQ(s.com.A)(s.com.B)-- Point vs vector: Proves that pair P's triangle inequality is distance(A,A) ≤ distance(A,B) + distance(B,A), a geometric law on its points.example(s:PairState3.P):(ForPhysLib.Kinded.Space.distanceQ(s.com.A)(s.com.A)).magnitude≤(ForPhysLib.Kinded.Space.distanceQ(s.com.A)(s.com.B)).magnitude+(ForPhysLib.Kinded.Space.distanceQ(s.com.B)(s.com.A)).magnitude:=ForPhysLib.Kinded.Space.distanceQ_triangle(s.com.A)(s.com.B)(s.com.A)
4. Bare frames. The vector fed to the three upstream laws is derived from this state's
two centres. All three transports accept it because F.Vector records a frame but not a
physical role. The displacement-plus-origin-velocity sum also elaborates. Both are
accepted but physically wrong when that vector is meant to be a displacement.
defbarePairDisplacement{π:PairId}(s:PairState3π)(F:ReferenceFrame3)(t:Time):F.Vector:=(ReferenceFrame.Vector.dispEquiv(frame:=F)(F.timeEquiv.symmt)).symm(s.com.A-ᵥs.com.B)-- Frame safety: Bare vectors erase physical frame and kind, so all three transports accept pair P's A–B displacement; only geometric is correct, and kinded `kBoostTransport` refuses it.example(s:PairState3.P)(FG:ReferenceFrame3)(t:Time)(u:EuclideanSpaceℝ(Fin3)):G.Vector×G.Vector×G.Vector:=letv:=barePairDisplacementsFt(geometricTransportFGtv,boostTransportFGtuv,originShiftTransportFGtv)-- Frame safety: Bare EuclideanSpace vectors accept adding pair P's displacement to cart velocity; the unindexed result cannot catch this physically invalid sum.example(s:PairState3.P)(cart:ReferenceFrame3)(hCart:cart.IsInertial):EuclideanSpaceℝ(Fin3):=(s.com.A-ᵥs.com.B)+hCart.velocity
5. Kinded frames. Frame components must enter through the frame's own dispEquiv.
With KVector, the displacement goes through geometric transport, and an average
velocity computed from two same-pair centre states goes through the boost law. The
observer-independence theorem shows that geometric transport preserves the displacement.
The wrong boost on a displacement and a velocity-plus-force sum are pinned refusals.
/- Frame components must enter through the frame's own `dispEquiv`. -/defpairDisplacementInFrame{π:PairId}(F:ReferenceFrame3)(t:Time)(s:PairState3π):KVectorFForPhysLib.Kinds.Space.displacement:=⟨⟨(barePairDisplacementsFt).components⟩⟩defaverageVelocityOfA{π:PairId}(earlierlater:PairState3π)(elapsed:QuantitydurationKℝ)(h:elapsed.magnitude≠0):QuantityvelocityK(EuclideanSpaceℝ(Fin3)):=⟨(ifhzero:elapsed.magnitude=0thenFalse.elim(hhzero)elseelapsed.magnitude⁻¹)•(later.com.A-ᵥearlier.com.A)⟩defaverageVelocityInFrame{π:PairId}(F:ReferenceFrame3)(t:Time)(earlierlater:PairState3π)(elapsed:QuantitydurationKℝ)(h:elapsed.magnitude≠0):KVectorFvelocityK:=⟨⟨((ReferenceFrame.Vector.dispEquiv(frame:=F)(F.timeEquiv.symmt)).symm(averageVelocityOfAearlierlaterelapsedh).magnitude).components⟩⟩-- Frame safety: Constructs a bearer-free `KVector G displacement` for pair P via geometric transport; frame and kind remain indexed, but P and Q displacements share a type.example(s:PairState3.P)(FG:ReferenceFrame3)(t:Time):KVectorGForPhysLib.Kinds.Space.displacement:=kGeometricTransportFGt(pairDisplacementInFrameFts)/-- Frame safety: Proves that geometric transport of pair P's displacement from F to G yields its G representation, so displacement is observer-independent. -/theorempairDisplacement_observer_independent{π:PairId}(FG:ReferenceFrame3)(t:Time)(s:PairState3π):kGeometricTransportFGt(pairDisplacementInFrameFts)=pairDisplacementInFrameGts:=π:PairIdF:ReferenceFrame3G:ReferenceFrame3t:Times:PairState3π⊢ kGeometricTransportFGt(pairDisplacementInFrameFts)=pairDisplacementInFrameGtsπ:PairIdF:ReferenceFrame3G:ReferenceFrame3t:Times:PairState3πhη:{components:=(barePairDisplacementsFt).components}=barePairDisplacementsFt⊢ kGeometricTransportFGt(pairDisplacementInFrameFts)=pairDisplacementInFrameGtsπ:PairIdF:ReferenceFrame3G:ReferenceFrame3t:Times:PairState3πhη:{components:=(barePairDisplacementsFt).components}=barePairDisplacementsFt⊢ {q:={magnitude:=((ReferenceFrame.Vector.dispEquiv(G.timeEquiv.symmt)).symm((ReferenceFrame.Vector.dispEquiv(F.timeEquiv.symmt)){components:=(barePairDisplacementsFt).components})).components}}={q:={magnitude:=(barePairDisplacementsGt).components}}π:PairIdF:ReferenceFrame3G:ReferenceFrame3t:Times:PairState3πhη:{components:=(barePairDisplacementsFt).components}=barePairDisplacementsFt⊢ {q:={magnitude:=((ReferenceFrame.Vector.dispEquiv(G.timeEquiv.symmt)).symm((ReferenceFrame.Vector.dispEquiv(F.timeEquiv.symmt))(barePairDisplacementsFt))).components}}={q:={magnitude:=(barePairDisplacementsGt).components}}simp[barePairDisplacement]All goals completed! 🐙-- Frame safety: Constructs a bearer-free `KVector G velocityK` for body A's average velocity via boost transport; the type cannot distinguish pair P from Q.example(earlierlater:PairState3.P)(elapsed:QuantitydurationKℝ)(h:elapsed.magnitude≠0)(FG:ReferenceFrame3)(t:Time)(u:QuantityvelocityK(EuclideanSpaceℝ(Fin3))):KVectorGvelocityK:=kBoostTransportFGtu(averageVelocityInFrameFtearlierlaterelapsedh)-- Frame safety: Refused: type mismatch between pair P's KVector displacement and the KVector velocity required by boost transport; displacement cannot be boosted as velocity./--
error: Application type mismatch: The argument
pairDisplacementInFrame F t s
has type
KVector F displacement
but is expected to have type
KVector F velocityK
in the application
kBoostTransport F G t u (pairDisplacementInFrame F t s)
-/#guard_msgs(whitespace:=lax)inexample(FG:ReferenceFrame3)(t:Time)(u:QuantityvelocityK(EuclideanSpaceℝ(Fin3)))(s:PairState3.P):=kBoostTransportFGtu(pairDisplacementInFrameFts)-- Kind vs dimension: Refused: no HAdd instance combines frame-F velocity and force vectors, preventing addition of unlike physical kinds./--
error: failed to synthesize instance of type class
HAdd (KVector F velocityK) (KVector F forceK) ?m.9
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
-/#guard_msgs(whitespace:=lax)inexample(F:ReferenceFrame3)(v:KVectorFvelocityK)(force:KVectorFforceK):=v+force
6. The observer moves.origin_displacement_eq states the cart frame's own origin
motion over elapsed time. The pair's state-derived displacement still cannot be added to
that frame's kinded velocity.
-- Frame safety: Proves that the inertial cart's origin-displacement magnitude equals elapsed time times cart-velocity magnitude; the law belongs to the cart frame.example(cart:ReferenceFrame3)(hCart:cart.IsInertial)(t₁t₂:Time):(ForPhysLib.Kinded.Space.displacementQ(cart.origint₂)(cart.origint₁)).magnitude=(elapsedQt₁t₂).magnitude•(frameVelocityQhCart).magnitude:=origin_displacement_eqcarthCartt₁t₂-- Kind vs dimension: Refused: no HAdd instance combines displacement and velocity quantities, preventing addition of unlike vector kinds./--
error: failed to synthesize instance of type class
HAdd (Quantity displacement (EuclideanSpace ℝ (Fin 3))) (Quantity velocityK (EuclideanSpace ℝ (Fin 3))) ?m.13
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
-/#guard_msgs(whitespace:=lax)inexample(s:PairState3.P)(cart:ReferenceFrame3)(hCart:cart.IsInertial):=ForPhysLib.Kinded.Space.displacementQ(s.com.A)(s.com.B)+frameVelocityQhCart
7. Adoption ladder. The five Space stages go from Kinds, through Metrology,
Kinded and Operators, to Audits. Stage 3's operator-built area is computed from this
state's A–B displacement and a probe-point displacement; its magnitude law is accepted,
while area × area is refused. Stage 4 audits the boundary and anchors the API map.
defpairSpanArea{π:PairId}(s:PairState3π)(p:Space3):QuantityForPhysLib.Kinds.Space.areaℝ:=ForPhysLib.Operators.Space.spanArea(ForPhysLib.Kinded.Space.displacementQ(s.com.A)(s.com.B))(ForPhysLib.Kinded.Space.displacementQ(s.com.A)p)/-- Point vs vector: Proves that pair P's span-area magnitude from A–B and A–p displacements is the product of their norms. -/lemmapairSpanArea_magnitude{π:PairId}(s:PairState3π)(p:Space3):(pairSpanAreasp).magnitude=‖(ForPhysLib.Kinded.Space.displacementQ(s.com.A)(s.com.B)).magnitude‖*‖(ForPhysLib.Kinded.Space.displacementQ(s.com.A)p).magnitude‖:=ForPhysLib.Operators.Space.spanArea_magnitude__-- Point vs vector: Constructs a bearer-free `Quantity area` from pair P's A–B and A–p displacements; its type cannot distinguish areas from other pairs or points.example(s:PairState3.P)(p:Space3):QuantityForPhysLib.Kinds.Space.areaℝ:=pairSpanAreasp-- Point vs vector: Proves that pair P's span-area magnitude equals the product of its A–B and A–p displacement norms.example(s:PairState3.P)(p:Space3):(pairSpanAreasp).magnitude=‖(ForPhysLib.Kinded.Space.displacementQ(s.com.A)(s.com.B)).magnitude‖*‖(ForPhysLib.Kinded.Space.displacementQ(s.com.A)p).magnitude‖:=pairSpanArea_magnitudesp-- Kind vs dimension: Refused: no HMul instance licenses area times area, preventing an unregistered product of two area quantities./--
error: failed to synthesize instance of type class
HMul (Quantity area ℝ) (Quantity area ℝ) ?m.9
Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
-/#guard_msgs(whitespace:=lax)inexample(s:PairState3.P)(p:Space3):=pairSpanAreasp*pairSpanAreasp
The Space adoption files, in order, are ForPhysLib/Kinds/Space.lean,
ForPhysLib/Metrology/Space.lean, ForPhysLib/Kinded/Space.lean,
ForPhysLib/Operators/Space.lean, and ForPhysLib/Audits/Space.lean. The final audit
stage is wired to Space/API-map.md by Space.checked_by.yaml.
Kind vocabulary for length, distance, position vector, displacement, and area.
1
ForPhysLib/Metrology/Space.lean
Dimension pairings and the kind algebra.
2
ForPhysLib/Kinded/Space.lean
positionQ, displacementQ, distanceQ, and lengthOf.
3
ForPhysLib/Operators/Space.lean
The curated operator table: spanArea is accepted, area × area is not.
4
ForPhysLib/Audits/Space.lean and Space.checked_by.yaml
Boundary and API-map audits under build checks.
The Stage-3 accepted form is
spanArea v w : Quantity area ℝ, with magnitude
‖v.magnitude‖ * ‖w.magnitude‖; the product of two areas has no registration. Stage 4
audits the authored boundary and ties the API map to its Lean declarations.
Keep L4 independent: define local PairId | P | Q and Body | A | B.
Preserve nominal identity: one name is one system; records under it are states,
configurations, or rival estimates; distinct names are distinct systems.
Use the exact PairState3.com fields for all accepted position, displacement,
distance, velocity, and area forms.
Keep the distance bearer pair-indexed in HCP; do not alter ForPhysLib's distanceQ.
Reuse the Space and ReferenceFrame APIs, and pin each requested kind refusal.
Label the accepted unkinded frame examples wrong; they do not encode physical role.
Recap, rather than rewrite, Space Stages 0–4 and point to Stage 4 audits.