-
Notifications
You must be signed in to change notification settings - Fork 251
[Add] padRight properties to Data.Vec.Properties #2769
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
See also: #2770 . Even if the types of the Tat being the case, I'll shout out to @JacquesCarette as to whether we go for this PR as is, and refactor downstream, or mark this blocking on #2770 ? |
I should have minded my manners better, and thanked you for the PR before piling in with my nitpicks! These are all, in whatever form they eventually take, a useful contribution... and since |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi!
Thanks for your comments! I've made the necessary changes based on your feedback. I just had a small issue with the last point — the irrelevant part of the type signature.
Looking forward to your review of this version!
Great idea for the lemmas for truncate
, will definitely look into that!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More nitpicks, I'm afraid, but otherwise looks good to go...
... but you'll need to write CHANGELOG
entries as well. Suggest you do this once the reset after the v2.3 release is complete, though...
... UPDATED which has now taken place. So, if you look at CHANGELOG.md
, you'll see under Additions to existing modules
... please add the lemma names with their types, and you can see existing versions under eg CHANGELOG/v2.2.md
to see formatting conventions etc.
padRight-trans : ∀ {p} (m≤n : m ≤ n) (n≤p : n ≤ p) (a : A) (xs : Vec A m) → | ||
padRight (≤-trans m≤n n≤p) a xs ≡ padRight n≤p a (padRight m≤n a xs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As previously, please don't use p
here, when o
would conventionally be better.
padRight-trans : ∀ {p} (m≤n : m ≤ n) (n≤p : n ≤ p) (a : A) (xs : Vec A m) → | |
padRight (≤-trans m≤n n≤p) a xs ≡ padRight n≤p a (padRight m≤n a xs) | |
padRight-trans : ∀ (m≤n : m ≤ n) (n≤o : n ≤ o) (a : A) (xs : Vec A m) → | |
padRight (≤-trans m≤n n≤o) a xs ≡ padRight n≤o a (padRight m≤n a xs) |
padRight-trans z≤n n≤p a [] = padRight-replicate n≤p a | ||
padRight-trans (s≤s m≤n) (s≤s n≤p) a (x ∷ xs) = cong (x ∷_) (padRight-trans m≤n n≤p a xs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LIkewise
padRight-trans z≤n n≤p a [] = padRight-replicate n≤p a | |
padRight-trans (s≤s m≤n) (s≤s n≤p) a (x ∷ xs) = cong (x ∷_) (padRight-trans m≤n n≤p a xs) | |
padRight-trans z≤n n≤o a [] = padRight-replicate n≤o a | |
padRight-trans (s≤s m≤n) (s≤s n≤o) a (x ∷ xs) = cong (x ∷_) (padRight-trans m≤n n≤o a xs) |
(a : A) (b : B) (xs : Vec A m) (ys : Vec B p) → | ||
zipWith f (padRight m≤n a xs) (padRight (≤-trans p≤m m≤n) b ys) ≡ | ||
padRight m≤n (f a b) (zipWith f xs (padRight p≤m b ys)) | ||
padRight-zipWith₁ {p} f m≤n p≤m a b xs ys = trans (cong (zipWith f (padRight m≤n a xs)) (padRight-trans p≤m m≤n b ys)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whatever else above regarding m n o/p
ordering of the variables...
padRight-zipWith₁ {p} f m≤n p≤m a b xs ys = trans (cong (zipWith f (padRight m≤n a xs)) (padRight-trans p≤m m≤n b ys)) | |
padRight-zipWith₁ f m≤n p≤m a b xs ys = trans (cong (zipWith f (padRight m≤n a xs)) (padRight-trans p≤m m≤n b ys)) |
Implicit p
isn't even used here, so it's much better to omit it to make your code less brittle.
padRight-zipWith₁ : ∀ {p} (f : A → B → C) (m≤n : m ≤ n) (p≤m : p ≤ m) | ||
(a : A) (b : B) (xs : Vec A m) (ys : Vec B p) → | ||
zipWith f (padRight m≤n a xs) (padRight (≤-trans p≤m m≤n) b ys) ≡ | ||
padRight m≤n (f a b) (zipWith f xs (padRight p≤m b ys)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh!
p
shouldn't be used here as an implicit; it's previously bound at module-level scope as avariable
of typeLevel
, whileo
is bound at typeNat
, so use that instead- what's the correct order of assumptions here? that
m ≤ n
precedep ≤ m
, or that you instead order them so thatm ≤ n ≤ o
and then fix up the relevant assumption uses to reflect that?
padRight-take m≤n a [] p = refl | ||
padRight-take (s≤s m≤n) a (x ∷ xs) p = cong (x ∷_) (padRight-take m≤n a xs (suc-injective p)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't use p
here as a pattenr variable for an equation, especially given that it is already implicitly bound above at type Level... etc.
Instead use eq
or the assumption name you have already chosen in the lemma statement (reduce cognitive load on the reader as the implied design heuristic here)
padRight-updateAt {n = suc n} (s≤s m≤n) (y ∷ xs) f zero x = refl | ||
padRight-updateAt {n = suc n} (s≤s m≤n) (y ∷ xs) f (suc i) x = cong (y ∷_) (padRight-updateAt m≤n xs f i x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
padRight-updateAt {n = suc n} (s≤s m≤n) (y ∷ xs) f zero x = refl | |
padRight-updateAt {n = suc n} (s≤s m≤n) (y ∷ xs) f (suc i) x = cong (y ∷_) (padRight-updateAt m≤n xs f i x) | |
padRight-updateAt {n = suc _} (s≤s m≤n) (y ∷ xs) f zero x = refl | |
padRight-updateAt {n = suc _} (s≤s m≤n) (y ∷ xs) f (suc i) x = cong (y ∷_) (padRight-updateAt m≤n xs f i x) |
The actual n
isn't used subsequently on the LHS, nor on the RHS, so omitting it in favour of a wildcard _
makes the code less brittle.
padRight-updateAt : ∀ (m≤n : m ≤ n) (xs : Vec A m) (f : A → A) (i : Fin m) (x : A) → | ||
updateAt (padRight m≤n x xs) (inject≤ i m≤n) f ≡ | ||
padRight m≤n x (updateAt xs i f) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the right argument order here? A heuristic I learnt from @JacquesCarette would be: args that vary most should be rightmost, those that are invariant/vary less should be leftmost, together with the heuristic that says that argument order for lemmas should try to follow the argument order for the 'main' function being characterised, so here at least something like:
padRight-updateAt : ∀ (m≤n : m ≤ n) (xs : Vec A m) (f : A → A) (i : Fin m) (x : A) → | |
updateAt (padRight m≤n x xs) (inject≤ i m≤n) f ≡ | |
padRight m≤n x (updateAt xs i f) | |
padRight-updateAt : ∀ (m≤n : m ≤ n) (x : A) (xs : Vec A m) (f : A → A) (i : Fin m) → | |
updateAt (padRight m≤n x xs) (inject≤ i m≤n) f ≡ | |
padRight m≤n x (updateAt xs i f) |
with the position of f
being moot, but perhaps should be rightmost to reflect its arg position in the function calls?
cast-replicate {m = zero} {n = zero} _ _ = refl | ||
cast-replicate {m = suc _} {n = suc _} eq x = cong (x ∷_) (cast-replicate (suc-injective eq) x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alignment?
cast-replicate {m = zero} {n = zero} _ _ = refl | |
cast-replicate {m = suc _} {n = suc _} eq x = cong (x ∷_) (cast-replicate (suc-injective eq) x) | |
cast-replicate {m = zero} {n = zero} _ _ = refl | |
cast-replicate {m = suc _} {n = suc _} eq x = cong (x ∷_) (cast-replicate (suc-injective eq) x) |
This PR adds several equational properties for padRight to Data.Vec.Properties, extending the standard vector operations toolkit with useful lemmas for reasoning about padding on the right.
Added properties:
Each property is proven by structural induction and uses standard lemmas such as
zipWith-replicate, map-replicate, and inject≤.
Authored by : @jmougeot