@@ -487,3 +487,60 @@ htShift i g c dg di (Let q t1 t2) hlen (THLet d1 d2 _ a' h1 h2 prf) =
487487 uaddUshift (uscale q d1g) (uscale q d1i) d2g d2i dg di hg hi)
488488htShift i g c dg di (MkEcho m aE bE t) hlen (THEcho h) = THEcho (htShift i g c dg di t hlen h)
489489htShift i g c dg di (Weaken t) hlen (THWeaken h) = THWeaken (htShift i g c dg di t hlen h)
490+
491+ -- ----------------------------------------------------------
492+ -- 4c. Substitution core — accounting algebra
493+ -- ----------------------------------------------------------
494+
495+ ||| Iterated weakening shift: `shiftn k = (shift 0)` iterated `k` times.
496+ ||| The cumulative shift the substituted term carries after descending `k`
497+ ||| binders (mirrors Coq `shiftn`).
498+ public export
499+ shiftn : Nat -> Tm -> Tm
500+ shiftn Z u = u
501+ shiftn (S k) u = shift 0 (shiftn k u)
502+
503+ ||| `ht_shift0`: weaken a derivation by one fresh `Zero`-usage binder — the
504+ ||| `htShift` instance at `i = TEmpty`.
505+ public export
506+ htShift0 : (g : Tctx) -> (c : Ty) -> (dg : Uvec) -> (t : Tm)
507+ -> Has g dg t a -> Has (TSnoc g c) (USnoc dg Zero ) (shift 0 t) a
508+ htShift0 g c dg t h = htShift TEmpty g c dg UEmpty t Refl h
509+
510+ ||| Middle-four exchange for `qAdd` (pure semiring rearrangement): groups the
511+ ||| inner pair so the additive accounting can be re-associated.
512+ qAddRearrange : (w, x, y, z : Q)
513+ -> qAdd (qAdd w x) (qAdd y z) = qAdd (qAdd w y) (qAdd x z)
514+ qAddRearrange w x y z =
515+ trans (qAddAssoc w x (qAdd y z))
516+ (trans (cong (qAdd w) midSwap) (sym (qAddAssoc w y (qAdd x z))))
517+ where
518+ midSwap : qAdd x (qAdd y z) = qAdd y (qAdd x z)
519+ midSwap = trans (sym (qAddAssoc x y z))
520+ (trans (cong (\ u => qAdd u z) (qAddComm x y)) (qAddAssoc y x z))
521+
522+ ||| The Q-semiring identity behind substituting through an additive split
523+ ||| (mirrors Coq `q_reassoc`; derived from the named semiring laws, no
524+ ||| 3^6-case enumeration).
525+ qReassoc : (dg1, dg2, du, q', q1, q2 : Q)
526+ -> qAdd (qAdd dg1 (qMul q' dg2)) (qMul (qAdd q1 (qMul q' q2)) du)
527+ = qAdd (qAdd dg1 (qMul q1 du)) (qMul q' (qAdd dg2 (qMul q2 du)))
528+ qReassoc dg1 dg2 du q' q1 q2 =
529+ trans (cong (qAdd (qAdd dg1 (qMul q' dg2)))
530+ (trans (qMulDistribR q1 (qMul q' q2) du)
531+ (cong (qAdd (qMul q1 du)) (qMulAssoc q' q2 du))))
532+ (trans (qAddRearrange dg1 (qMul q' dg2) (qMul q1 du) (qMul q' (qMul q2 du)))
533+ (cong (qAdd (qAdd dg1 (qMul q1 du)))
534+ (sym (qMulDistribL q' dg2 (qMul q2 du)))))
535+
536+ ||| `uadd D (Zero · E) = D` (lengths matched): the zero-scaled right summand
537+ ||| is the additive identity. (Mirrors Coq `uadd_uscaleZero_r`.)
538+ public export
539+ uaddUscaleZeroR : (d, e : Uvec) -> ulen d = ulen e -> uadd d (uscale Zero e) = Just d
540+ uaddUscaleZeroR UEmpty UEmpty _ = Refl
541+ uaddUscaleZeroR UEmpty (USnoc _ _ ) prf = void (zNotS' prf)
542+ uaddUscaleZeroR (USnoc _ _ ) UEmpty prf = void (sNotZ' prf)
543+ uaddUscaleZeroR (USnoc d qd) (USnoc e qe) prf =
544+ rewrite uaddUscaleZeroR d e (predEq' prf) in
545+ rewrite qMulZeroL qe in
546+ rewrite qAddZeroR qd in Refl
0 commit comments