Skip to content

Commit aa74c05

Browse files
hyperpolymathclaude
andcommitted
agda(EchoIndexed): per-decoration composition rung
Adds the role-indexed analogue of `map-over-comp` (Echo.agda) and `degrade-comp` / `degrade-compose` (EchoGraded.agda): * `map-role-indexed-comp` — functoriality of `map-role-indexed`: composing two decoration arrows (u, ρ) and (u', ρ') and acting once equals acting in sequence. Proof routes through `cong-trans`, `cong-∘`, and two `trans-assoc` rewrites. * `forget-role-map-role-indexed` — naturality of `forget-role` along decoration arrows: forgetting after mapping equals `map-over` after forgetting. Holds definitionally. Two local auxiliaries (`cong-trans`, `cong-∘`) keep the module self-contained, mirroring the existing `cong-id` style. All headlines pinned in `Smoke.agda`. EchoIndexed.agda builds clean under `--safe --without-K`, no postulates introduced. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 65fcdda commit aa74c05

2 files changed

Lines changed: 90 additions & 0 deletions

File tree

proofs/agda/EchoIndexed.agda

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,85 @@ map-role-indexed-id :
6565
map-role-indexed-id (x , pᵢ , p)
6666
rewrite cong-id pᵢ = refl
6767

68+
-- Auxiliaries: `cong` distributes over `trans`, and nested `cong`
69+
-- factors through function composition. Both are standard
70+
-- propositional-equality facts but kept local to keep this module
71+
-- self-contained and aligned with the existing `cong-id` style.
72+
cong-trans :
73+
{a b} {A : Set a} {B : Set b} (g : A B) {x y z : A}
74+
(p : x ≡ y) (q : y ≡ z)
75+
cong g (trans p q) ≡ trans (cong g p) (cong g q)
76+
cong-trans g refl q = refl
77+
78+
cong-∘ :
79+
{a b c} {A : Set a} {B : Set b} {C : Set c}
80+
(g : B C) (f : A B) {x y : A} (p : x ≡ y)
81+
cong g (cong f p) ≡ cong (λ z g (f z)) p
82+
cong-∘ g f refl = refl
83+
84+
-- Per-decoration composition law: applying two decoration maps in
85+
-- sequence gives the same result as applying their composite. This
86+
-- is the role-indexed analogue of `map-over-comp` (Echo.agda) and the
87+
-- `degrade-comp` step in the per-decoration composition rung
88+
-- established in EchoGraded.agda.
89+
--
90+
-- The decoration here is the (role-index, role-projection) pair
91+
-- (I, ι); a decoration arrow `(u, ρ, comm-f, comm-ι)` from
92+
-- (A, I, ι, f) to (A', I', ι', f') sits over a fixed codomain B.
93+
-- Composition of two such arrows is the obvious componentwise
94+
-- composition (u' ∘ u, ρ' ∘ ρ) with the obligatory commutation
95+
-- proofs glued by `trans` and `cong`. This lemma certifies that
96+
-- gluing is functorial.
97+
map-role-indexed-comp :
98+
{a a' a'' b i i' i''}
99+
{A : Set a} {A' : Set a'} {A'' : Set a''} {B : Set b}
100+
{I : Set i} {I' : Set i'} {I'' : Set i''}
101+
(f : A B) (f' : A' B) (f'' : A'' B)
102+
: A I) (ι' : A' I') (ι'' : A'' I'')
103+
(u : A A') (u' : A' A'')
104+
: I I') (ρ' : I' I'')
105+
(comm-f : x f' (u x) ≡ f x)
106+
(comm-f' : x' f'' (u' x') ≡ f' x')
107+
(comm-ι : x ι' (u x) ≡ ρ (ι x))
108+
(comm-ι' : x' ι'' (u' x') ≡ ρ' (ι' x'))
109+
{idx : I} {y : B}
110+
(e : Echoᵢ I ι f idx y)
111+
map-role-indexed f' f'' ι' ι'' u' ρ' comm-f' comm-ι'
112+
(map-role-indexed f f' ι ι' u ρ comm-f comm-ι e)
113+
≡ map-role-indexed f f'' ι ι'' (λ x u' (u x)) (λ i ρ' (ρ i))
114+
(λ x trans (comm-f' (u x)) (comm-f x))
115+
(λ x trans (comm-ι' (u x)) (cong ρ' (comm-ι x)))
116+
e
117+
map-role-indexed-comp f f' f'' ι ι' ι'' u u' ρ ρ' comm-f comm-f' comm-ι comm-ι'
118+
(x , pᵢ , p)
119+
rewrite cong-trans ρ' (comm-ι x) (cong ρ pᵢ)
120+
| cong-∘ ρ' ρ pᵢ
121+
| trans-assoc (comm-ι' (u x)) (cong ρ' (comm-ι x))
122+
(cong (λ z ρ' (ρ z)) pᵢ)
123+
| trans-assoc (comm-f' (u x)) (comm-f x) p
124+
= refl
125+
126+
-- Forgetting the role index is natural with respect to decoration
127+
-- maps: applying `forget-role` after a `map-role-indexed` is the
128+
-- same as applying the underlying `map-over` after forgetting. This
129+
-- says the role-indexed layer is a strict refinement of the bare
130+
-- `Echo` story — no information is silently introduced or lost
131+
-- when stripping the role.
132+
forget-role-map-role-indexed :
133+
{a a' b i i'}
134+
{A : Set a} {A' : Set a'} {B : Set b}
135+
{I : Set i} {I' : Set i'}
136+
(f : A B) (f' : A' B)
137+
: A I) (ι' : A' I')
138+
(u : A A') (ρ : I I')
139+
(comm-f : x f' (u x) ≡ f x)
140+
(comm-ι : x ι' (u x) ≡ ρ (ι x))
141+
{idx : I} {y : B}
142+
(e : Echoᵢ I ι f idx y)
143+
forget-role (map-role-indexed f f' ι ι' u ρ comm-f comm-ι e)
144+
≡ map-over (u , comm-f) (forget-role e)
145+
forget-role-map-role-indexed f f' ι ι' u ρ comm-f comm-ι (x , pᵢ , p) = refl
146+
68147
-- Trace-level role-indexed example.
69148
data Role : Set where
70149
user : Role

proofs/agda/Smoke.agda

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ open import EchoApprox using
3939
; module Approx
4040
)
4141

42+
open import EchoIndexed using
43+
( Echoᵢ
44+
; echoᵢ-intro
45+
; forget-role
46+
; role-sound
47+
; map-role-indexed
48+
; map-role-indexed-id
49+
; map-role-indexed-comp
50+
; forget-role-map-role-indexed
51+
)
52+
4253
open import EchoChoreo using
4354
( Role
4455
; Global

0 commit comments

Comments
 (0)