Skip to content

Commit dcf89d0

Browse files
andreasabelMatthewDaggitt
authored andcommitted
Added Data.Vec.updateAt and its properties. (#510)
1 parent 3b4d171 commit dcf89d0

File tree

3 files changed

+179
-35
lines changed

3 files changed

+179
-35
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,13 @@ Other minor additions
554554
```agda
555555
respects : P Respects _≈_ → (All P) Respects _≋_
556556
```
557+
A generalization of single point overwrite `_[_]≔_`
558+
to single-point modification `_[_]%=_`
559+
(alias with different argument order: `updateAt`):
560+
```agda
561+
_[_]%=_ : Vec A n → Fin n → (A → A) → Vec A n
562+
updateAt : Fin n → (A → A) → Vec A n → Vec A n
563+
```
557564

558565
* Added new functions to `Data.List.Base`:
559566
```agda
@@ -573,6 +580,8 @@ Other minor additions
573580
_∷=_ : x ∈ xs → A → List A
574581
_─_ : (xs : List A) → x ∈ xs → List A
575582
```
583+
Added laws for `updateAt`.
584+
Now laws for `_[_]≔_` are special instances of these.
576585

577586
* Added new proofs to `Data.List.Membership.Setoid.Properties`:
578587
```agda
@@ -727,6 +736,10 @@ Other minor additions
727736
×-magma : Symmetric-kind → (ℓ : Level) → Magma _ _
728737
```
729738

739+
* Added new definitions to `Relation.Binary.PropositionalEquality`:
740+
- `_≡_↾¹_` equality of functions at a single point
741+
- `_≡_↾_` equality of functions at a subset of the domain
742+
730743
* Added new proofs to `Relation.Binary.Consequences`:
731744
```agda
732745
wlog : Total _R_ → Symmetric Q → (∀ a b → a R b → Q a b) → ∀ a b → Q a b

src/Data/Vec.agda

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,21 @@ remove (suc i) (x ∷ y ∷ xs) = x ∷ remove i (y ∷ xs)
6060

6161
-- Update.
6262

63-
infixl 6 _[_]≔_
63+
infixl 6 _[_]%=_ _[_]≔_
64+
65+
-- updateAt i f xs modifies the i-th element of xs according to f
66+
67+
updateAt : {a n} {A : Set a} Fin n (A A) Vec A n Vec A n
68+
updateAt zero f (x ∷ xs) = f x ∷ xs
69+
updateAt (suc i) f (x ∷ xs) = x ∷ updateAt i f xs
70+
71+
_[_]%=_ : {a n} {A : Set a} Vec A n Fin n (A A) Vec A n
72+
xs [ i ]%= f = updateAt i f xs
73+
74+
-- xs [ i ]≔ y overwrites the i-th element of xs with y
6475

6576
_[_]≔_ : {a n} {A : Set a} Vec A n Fin n A Vec A n
66-
(x ∷ xs) [ zero ]≔ y = y ∷ xs
67-
(x ∷ xs) [ suc i ]≔ y = x ∷ xs [ i ]≔ y
77+
xs [ i ]≔ y = xs [ i ]%= λ _ y
6878

6979
------------------------------------------------------------------------
7080
-- Operations for transforming vectors

src/Data/Vec/Properties.agda

Lines changed: 153 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ open import Function.Inverse using (_↔_; inverse)
2525
open import Relation.Binary hiding (Decidable)
2626
open import Relation.Binary.PropositionalEquality as P
2727
using (_≡_; _≢_; refl; _≗_)
28+
open import Relation.Binary.HeterogeneousEquality as H using (_≅_; refl)
2829
open import Relation.Unary using (Pred; Decidable)
2930
open import Relation.Nullary using (yes; no)
3031

@@ -67,7 +68,7 @@ module _ {a} {A : Set a} where
6768
lookup⇒[]= : {n} (i : Fin n) {x : A} xs
6869
lookup i xs ≡ x xs [ i ]= x
6970
lookup⇒[]= zero (_ ∷ _) refl = here
70-
lookup⇒[]= (suc i) (_ ∷ xs) p = there (lookup⇒[]= i xs p)
71+
lookup⇒[]= (suc i) (_ ∷ xs) p = there (lookup⇒[]= i xs p)
7172

7273
[]=↔lookup : {n i} {x} {xs : Vec A n}
7374
xs [ i ]= x ↔ lookup i xs ≡ x
@@ -89,59 +90,171 @@ module _ {a} {A : Set a} where
8990
[]=⇒lookup∘lookup⇒[]= (suc i) (x ∷ xs) p =
9091
[]=⇒lookup∘lookup⇒[]= i xs p
9192

93+
------------------------------------------------------------------------
94+
-- updateAt (_[_]%=_)
95+
96+
module _ {a} {A : Set a} where
97+
98+
-- Defining properties of updateAt:
99+
100+
-- (+) updateAt i actually updates the element at index i.
101+
102+
updateAt-updates : {n} (i : Fin n) {f : A A} (xs : Vec A n) {x : A}
103+
xs [ i ]= x
104+
updateAt i f xs [ i ]= f x
105+
updateAt-updates zero (x ∷ xs) here = here
106+
updateAt-updates (suc i) (x ∷ xs) (there loc) = there (updateAt-updates i xs loc)
107+
108+
-- (-) updateAt i does not touch the elements at other indices.
109+
110+
updateAt-minimal : {n} (i j : Fin n) {f : A A} {x : A} (xs : Vec A n)
111+
i ≢ j
112+
xs [ i ]= x
113+
updateAt j f xs [ i ]= x
114+
updateAt-minimal zero zero (x ∷ xs) 0≢0 here = ⊥-elim (0≢0 refl)
115+
updateAt-minimal zero (suc j) (x ∷ xs) _ here = here
116+
updateAt-minimal (suc i) zero (x ∷ xs) _ (there loc) = there loc
117+
updateAt-minimal (suc i) (suc j) (x ∷ xs) i≢j (there loc) =
118+
there (updateAt-minimal i j xs (i≢j ∘ P.cong suc) loc)
119+
120+
-- The other properties are consequences of (+) and (-).
121+
-- We spell the most natural properties out.
122+
-- Direct inductive proofs are in most cases easier than just using
123+
-- the defining properties.
124+
125+
-- In the explanations, we make use of shorthand f = g ↾ x
126+
-- meaning that f and g agree at point x, i.e. f x ≡ g x.
127+
128+
-- updateAt i is a morphism from the monoid of endofunctions A → A
129+
-- to the monoid of endofunctions Vec A n → Vec A n
130+
131+
-- 1a. relative identity: f = id ↾ (lookup i xs)
132+
-- implies updateAt i f = id ↾ xs
133+
134+
updateAt-id-relative : {n} (i : Fin n) (xs : Vec A n) {f : A A}
135+
f (lookup i xs) ≡ lookup i xs
136+
updateAt i f xs ≡ xs
137+
updateAt-id-relative zero (x ∷ xs) eq = P.cong (_∷ xs) eq
138+
updateAt-id-relative (suc i) (x ∷ xs) eq = P.cong (x ∷_) (updateAt-id-relative i xs eq)
139+
140+
-- 1b. identity: updateAt i id ≗ id
141+
142+
updateAt-id : {n} (i : Fin n) (xs : Vec A n)
143+
updateAt i id xs ≡ xs
144+
updateAt-id i xs = updateAt-id-relative i xs refl
145+
146+
-- 2a. relative composition: f ∘ g = h ↾ (lookup i xs)
147+
-- implies updateAt i f ∘ updateAt i g ≗ updateAt i h
148+
149+
updateAt-compose-relative : {n} (i : Fin n) {f g h : A A} (xs : Vec A n)
150+
f (g (lookup i xs)) ≡ h (lookup i xs)
151+
updateAt i f (updateAt i g xs) ≡ updateAt i h xs
152+
updateAt-compose-relative zero (x ∷ xs) fg=h = P.cong (_∷ xs) fg=h
153+
updateAt-compose-relative (suc i) (x ∷ xs) fg=h =
154+
P.cong (x ∷_) (updateAt-compose-relative i xs fg=h)
155+
156+
-- 2b. composition: updateAt i f ∘ updateAt i g ≗ updateAt i (f ∘ g)
157+
158+
updateAt-compose : {n} (i : Fin n) {f g : A A}
159+
updateAt i f ∘ updateAt i g ≗ updateAt i (f ∘ g)
160+
updateAt-compose i xs = updateAt-compose-relative i xs refl
161+
162+
-- 3. congruence: updateAt i is a congruence wrt. extensional equality.
163+
164+
-- 3a. If f = g ↾ (lookup i xs)
165+
-- then updateAt i f = updateAt i g ↾ xs
166+
167+
updateAt-cong-relative : {n} (i : Fin n) {f g : A A} (xs : Vec A n)
168+
f (lookup i xs) ≡ g (lookup i xs)
169+
updateAt i f xs ≡ updateAt i g xs
170+
updateAt-cong-relative zero (x ∷ xs) f=g = P.cong (_∷ xs) f=g
171+
updateAt-cong-relative (suc i) (x ∷ xs) f=g = P.cong (x ∷_) (updateAt-cong-relative i xs f=g)
172+
173+
-- 3b. congruence: f ≗ g → updateAt i f ≗ updateAt i g
174+
175+
updateAt-cong : {n} (i : Fin n) {f g : A A}
176+
f ≗ g
177+
updateAt i f ≗ updateAt i g
178+
updateAt-cong i f≗g xs = updateAt-cong-relative i xs (f≗g (lookup i xs))
179+
180+
-- The order of updates at different indices i ≢ j does not matter.
181+
182+
-- This a consequence of updateAt-updates and updateAt-minimal
183+
-- but easier to prove inductively.
184+
185+
updateAt-commutes : {n} (i j : Fin n) {f g : A A}
186+
i ≢ j
187+
updateAt i f ∘ updateAt j g ≗ updateAt j g ∘ updateAt i f
188+
updateAt-commutes zero zero 0≢0 (x ∷ xs) = ⊥-elim (0≢0 refl)
189+
updateAt-commutes zero (suc j) i≢j (x ∷ xs) = refl
190+
updateAt-commutes (suc i) zero i≢j (x ∷ xs) = refl
191+
updateAt-commutes (suc i) (suc j) i≢j (x ∷ xs) =
192+
P.cong (x ∷_) (updateAt-commutes i j (i≢j ∘ P.cong suc) xs)
193+
194+
-- lookup after updateAt reduces.
195+
196+
-- For same index this is an easy consequence of updateAt-updates
197+
-- using []=↔lookup.
198+
199+
lookup∘updateAt : {n} (i : Fin n) {f : A A}
200+
lookup i ∘ updateAt i f ≗ f ∘ lookup i
201+
lookup∘updateAt i xs =
202+
[]=⇒lookup (updateAt-updates i xs (lookup⇒[]= i _ refl))
203+
204+
-- For different indices it easily follows from updateAt-minimal.
205+
206+
lookup∘updateAt′ : {n} (i j : Fin n) {f : A A}
207+
i ≢ j
208+
lookup i ∘ updateAt j f ≗ lookup i
209+
lookup∘updateAt′ i j xs i≢j =
210+
[]=⇒lookup (updateAt-minimal i j i≢j xs (lookup⇒[]= i _ refl))
211+
212+
-- Aliases for notation _[_]%=_
213+
214+
[]%=-id : {n} (xs : Vec A n) (i : Fin n) xs [ i ]%= id ≡ xs
215+
[]%=-id xs i = updateAt-id i xs
216+
217+
[]%=-compose : {n} (xs : Vec A n) (i : Fin n) {f g : A A}
218+
xs [ i ]%= f
219+
[ i ]%= g
220+
≡ xs [ i ]%= g ∘ f
221+
[]%=-compose xs i = updateAt-compose i xs
222+
92223
------------------------------------------------------------------------
93224
-- _[_]≔_ (update)
225+
--
226+
-- _[_]≔_ is defined in terms of updateAt, and all of its properties
227+
-- are special cases of the ones for updateAt.
94228

95229
module _ {a} {A : Set a} where
96230

97231
[]≔-idempotent : {n} (xs : Vec A n) (i : Fin n) {x₁ x₂ : A}
98232
(xs [ i ]≔ x₁) [ i ]≔ x₂ ≡ xs [ i ]≔ x₂
99-
[]≔-idempotent [] ()
100-
[]≔-idempotent (x ∷ xs) zero = refl
101-
[]≔-idempotent (x ∷ xs) (suc i) = P.cong (x ∷_) ([]≔-idempotent xs i)
233+
[]≔-idempotent xs i = updateAt-compose i xs
102234

103235
[]≔-commutes : {n} (xs : Vec A n) (i j : Fin n) {x y : A} i ≢ j
104236
(xs [ i ]≔ x) [ j ]≔ y ≡ (xs [ j ]≔ y) [ i ]≔ x
105-
[]≔-commutes [] () () _
106-
[]≔-commutes (x ∷ xs) zero zero 0≢0 = ⊥-elim $ 0≢0 refl
107-
[]≔-commutes (x ∷ xs) zero (suc i) _ = refl
108-
[]≔-commutes (x ∷ xs) (suc i) zero _ = refl
109-
[]≔-commutes (x ∷ xs) (suc i) (suc j) i≢j =
110-
P.cong (x ∷_) $ []≔-commutes xs i j (i≢j ∘ P.cong suc)
237+
[]≔-commutes xs i j i≢j = updateAt-commutes j i (i≢j ∘ P.sym) xs
111238

112239
[]≔-updates : {n} (xs : Vec A n) (i : Fin n) {x : A}
113240
(xs [ i ]≔ x) [ i ]= x
114-
[]≔-updates [] ()
115-
[]≔-updates (x ∷ xs) zero = here
116-
[]≔-updates (x ∷ xs) (suc i) = there ([]≔-updates xs i)
241+
[]≔-updates xs i = updateAt-updates i xs (lookup⇒[]= i xs refl)
117242

118243
[]≔-minimal : {n} (xs : Vec A n) (i j : Fin n) {x y : A} i ≢ j
119244
xs [ i ]= x (xs [ j ]≔ y) [ i ]= x
120-
[]≔-minimal [] () () _ _
121-
[]≔-minimal (x ∷ xs) .zero zero 0≢0 here = ⊥-elim (0≢0 refl)
122-
[]≔-minimal (x ∷ xs) .zero (suc j) _ here = here
123-
[]≔-minimal (x ∷ xs) (suc i) zero _ (there loc) = there loc
124-
[]≔-minimal (x ∷ xs) (suc i) (suc j) i≢j (there loc) =
125-
there ([]≔-minimal xs i j (i≢j ∘ P.cong suc) loc)
245+
[]≔-minimal xs i j i≢j loc = updateAt-minimal i j xs i≢j loc
126246

127247
[]≔-lookup : {n} (xs : Vec A n) (i : Fin n)
128248
xs [ i ]≔ lookup i xs ≡ xs
129-
[]≔-lookup [] ()
130-
[]≔-lookup (x ∷ xs) zero = refl
131-
[]≔-lookup (x ∷ xs) (suc i) = P.cong (_∷_ x) $ []≔-lookup xs i
249+
[]≔-lookup xs i = updateAt-id-relative i xs refl
132250

133251
lookup∘update : {n} (i : Fin n) (xs : Vec A n) x
134252
lookup i (xs [ i ]≔ x) ≡ x
135-
lookup∘update zero (_ ∷ xs) x = refl
136-
lookup∘update (suc i) (_ ∷ xs) x = lookup∘update i xs x
253+
lookup∘update i xs x = lookup∘updateAt i xs
137254

138255
lookup∘update′ : {n} {i j : Fin n} i ≢ j (xs : Vec A n) y
139256
lookup i (xs [ j ]≔ y) ≡ lookup i xs
140-
lookup∘update′ {i = zero} {zero} i≢j xs y = ⊥-elim (i≢j refl)
141-
lookup∘update′ {i = zero} {suc j} i≢j (x ∷ xs) y = refl
142-
lookup∘update′ {i = suc i} {zero} i≢j (x ∷ xs) y = refl
143-
lookup∘update′ {i = suc i} {suc j} i≢j (x ∷ xs) y =
144-
lookup∘update′ (i≢j ∘ P.cong suc) xs y
257+
lookup∘update′ {n} {i} {j} i≢j xs y = lookup∘updateAt′ i j i≢j xs
145258

146259
------------------------------------------------------------------------
147260
-- map
@@ -167,12 +280,17 @@ lookup-map : ∀ {a b n} {A : Set a} {B : Set b}
167280
lookup-map zero f (x ∷ xs) = refl
168281
lookup-map (suc i) f (x ∷ xs) = lookup-map i f xs
169282

283+
map-updateAt : {n a b} {A : Set a} {B : Set b}
284+
{f : A B} {g : A A} {h : B B} (xs : Vec A n) (i : Fin n)
285+
f (g (lookup i xs)) ≡ h (f (lookup i xs))
286+
map f (updateAt i g xs) ≡ updateAt i h (map f xs)
287+
map-updateAt (x ∷ xs) zero eq = P.cong (_∷ _) eq
288+
map-updateAt (x ∷ xs) (suc i) eq = P.cong (_ ∷_) (map-updateAt xs i eq)
289+
170290
map-[]≔ : {n a b} {A : Set a} {B : Set b}
171291
(f : A B) (xs : Vec A n) (i : Fin n) {x : A}
172292
map f (xs [ i ]≔ x) ≡ map f xs [ i ]≔ f x
173-
map-[]≔ f [] ()
174-
map-[]≔ f (x ∷ xs) zero = refl
175-
map-[]≔ f (x ∷ xs) (suc i) = P.cong (_ ∷_) $ map-[]≔ f xs i
293+
map-[]≔ f xs i = map-updateAt xs i refl
176294

177295
------------------------------------------------------------------------
178296
-- _++_
@@ -621,3 +739,6 @@ module _ {a} {A : Set a} where
621739
toList∘fromList : (xs : List A) toList (fromList xs) ≡ xs
622740
toList∘fromList List.[] = refl
623741
toList∘fromList (x List.∷ xs) = P.cong (x List.∷_) (toList∘fromList xs)
742+
743+
-- -}
744+
-- -}

0 commit comments

Comments
 (0)