-
Notifications
You must be signed in to change notification settings - Fork 429
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
feat: verify insertMany method for adding lists to HashMaps #6211
base: master
Are you sure you want to change the base?
feat: verify insertMany method for adding lists to HashMaps #6211
Conversation
Mathlib CI status (docs):
|
src/Std/Data/DHashMap/Basic.lean
Outdated
@@ -285,6 +285,11 @@ but will later become a primitive operation. | |||
⟨(Raw₀.insertMany ⟨m.1, m.2.size_buckets_pos⟩ l).1, | |||
(Raw₀.insertMany ⟨m.1, m.2.size_buckets_pos⟩ l).2 _ Raw.WF.insert₀ m.2⟩ | |||
|
|||
@[inline, inherit_doc Raw.insertList] def insertList (m : DHashMap α β) |
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.
I don't think we should expose an insertList
function as part of the public API. Here is how I imagined this working:
- you define
insertListₘ
(for example using the definition you have) - you prove a theorem
insertMany_eq_insertListₘ
inModel.lean
which rewritesinsertMany
applied to a list directly toinsertListₘ
- in
WF.lean
, you prove theoremstoListModel_insertListₘ
, (wfImp_insertListₘ
probably not needed) ,toListModel_insertMany
(which only applies to lists!) - all of the lemmas in
Internal/RawLemmas.lean
are stated in terms ofinsertMany
but only apply if the input is a list.
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.
I changed that. It remains open how to name the lemmas. I kept insertList
for now in the name. Using just insertMany
seems impractical in case someone verifies insertList for arrays, trees etc. insertMany_list
seemed a bit long
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.
Long lemma names aren't necessarily a problem (we have IDE autocomplete ;)), so insertMany_list
seems like the correct name to me.
d58354d
to
cea3723
Compare
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.
Most of my comments focus on things like naming which make sense to get exactly right before copying the lemmas a bunch of times, because it is more fun to change a name two times compared to changing it eight times :)
@@ -706,6 +706,29 @@ theorem wfImp_filter [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] {m | |||
rw [filter_eq_filterₘ] | |||
exact wfImp_filterₘ h | |||
|
|||
/-! # `insertListₘ` -/ | |||
theorem wfImp_insertListₘ [BEq α] [Hashable α] [EquivBEq α][LawfulHashable α] {m : Raw₀ α β} {l : List ((a : α) × β a)} (h : Raw.WFImp m.1) : Raw.WFImp (m.insertListₘ l).1 := by |
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.
This line is very long. If you have opened the Lean 4 workspace correctly, you should see a ruler at 100 columns. Please reformat your lines to stay within 100 columns.
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.
I have WordWrapper activated in my vs code and then the ruler isn't moved in the wrapped line, but thats probably an issue only affecting very few users. I can keep an eye on 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.
If I'm understanding you correctly this only occurs if your editor window is less than 100 columns wide? If so, yes, I don't think many users do it that way :)
@@ -706,6 +706,29 @@ theorem wfImp_filter [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] {m | |||
rw [filter_eq_filterₘ] | |||
exact wfImp_filterₘ h | |||
|
|||
/-! # `insertListₘ` -/ |
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.
/-! # `insertListₘ` -/ | |
/-! # `insertListₘ` -/ | |
(similar below)
apply ih (wfImp_insert h) | ||
apply List.insertList_perm_of_perm_first | ||
apply toListModel_insert h | ||
apply (wfImp_insert h).distinct |
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.
apply (wfImp_insert h).distinct | |
apply (wfImp_insert h).distinct | |
section | ||
variable {β: Type v} (m: Raw₀ α (fun _ => β)) | ||
|
||
theorem get?_insertMany_list_not_mem_const [EquivBEq α] [LawfulHashable α] |
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.
Should this not be called Const.get?_insertMany_of_contains_eq_false
?
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.
This theorem appers twice for Const.get
for general insertMany
and for Const.get
for Const.insertMany
, which would collapse via this name. I introduced the const to differentiate between the normal get
and this one, though I copied it also into the results in the Const
namespace.
getKey (insertManyIfNewUnit m l).1 k' h' = k := by | ||
simp_to_model using getKey_insertListIfNewUnit_mem | ||
|
||
theorem getKey_insertManyIfNewUnit_list_mem_both [EquivBEq α] [LawfulHashable α] |
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.
Let's avoid abbreviations as much as possible and derive theorem names as "mechanically" as possible. I would call this getKey_insertManyIfNewUnit_of_contains_of_contains
. Note the of
before hypotheses.
theorem getKey_insertManyIfNewUnit_list_mem_both [EquivBEq α] [LawfulHashable α] | ||
{l : List α} {k : α} | ||
{distinct : l.Pairwise (fun a b => (a == b) = false)} | ||
{mem : l.contains k} {mem' : m.contains k = true} {h'} (h : m.1.WF): |
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.
Here and in many other places, you should just write m.contains k
instead of m.contains k = true
when using a Prop
statement.
getKeyD (insertManyIfNewUnit m l).1 k fallback = getKeyD m k fallback := by | ||
simp_to_model using getKeyD_insertListIfNewUnit_mem_both | ||
|
||
theorem insertManyIfNewUnit_list_length [EquivBEq α] [LawfulHashable α] |
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.
We generally read function calls "outside-in", so the proper name here would be length_insertManyIfNewUnit
.
section | ||
variable {β: Type v} (m: Raw₀ α (fun _ => β)) | ||
|
||
theorem get?_insertMany_list_of_contains_eq_false_const [EquivBEq α] [LawfulHashable α] (h : m.1.WF) |
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.
Okay, I see the problem with naming these lemmas. I think the (admittedly slighly crazy) scheme we use for the naming here would be that the lemma lives in the namespace of the first thing that appears in the name and then other relevant namespaces are included in the theorem name as appropriate. So this lemma would be called Const.get?_insertMany_list_of_contains_eq_false
and the lemma you're currently calling Const.get?_insertMany_list_of_contains_eq_false
would be called Const.get?_constInsertMany_list_of_contains_eq_false
. Luckily, it's unlikely that end users will need to interact with these lemmas directly.
This PR verifies the
insertMany
method onHashMap
s for the special case of inserting lists.