Skip to content
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: HashMap.toList_insert_perm_of_not_mem #6304

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

kim-em
Copy link
Collaborator

@kim-em kim-em commented Dec 4, 2024

WIP, this is stacked on top of #6232, and may not make sense at all if that requires substantial revisions.

@github-actions github-actions bot temporarily deployed to lean-lang.org/lean4/doc December 4, 2024 11:19 Inactive
@github-actions github-actions bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Dec 4, 2024
@leanprover-community-bot
Copy link
Collaborator

Mathlib CI status (docs):

  • ❗ Mathlib CI can not be attempted yet, as the nightly-testing-2024-12-04 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-mathlib, Mathlib CI should run now. (2024-12-04 11:27:40)

Comment on lines +849 to +856
open _root_.List in
theorem toList_insert_perm_of_not_contains [EquivBEq α] [LawfulHashable α] (h : m.1.WF)
(k : α) (v : β k) (h' : m.contains k = false) :
(m.insert k v).1.toList ~ ⟨k, v⟩ :: m.1.toList := by
revert h'
simp_to_model
intro h'
exact Perm.trans (toListModel_insert (Raw.WF.out h)) (by simp [insertEntry, h'])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is how I had envisioned this working: you prove

private theorem perm_of_perm {l₁ l₂ l₃ : List α} (h : List.Perm l₁ l₂) :
    List.Perm l₁ l₃ ↔ List.Perm l₂ l₃ :=
  ⟨h.symm.trans, h.trans⟩

and add ← `(perm_of_perm) to congrNames. Then this lemma is proved like this:

Suggested change
open _root_.List in
theorem toList_insert_perm_of_not_contains [EquivBEq α] [LawfulHashable α] (h : m.1.WF)
(k : α) (v : β k) (h' : m.contains k = false) :
(m.insert k v).1.toList ~ ⟨k, v⟩ :: m.1.toList := by
revert h'
simp_to_model
intro h'
exact Perm.trans (toListModel_insert (Raw.WF.out h)) (by simp [insertEntry, h'])
open _root_.List in
theorem toList_insert_perm_of_not_contains [EquivBEq α] [LawfulHashable α] (h : m.1.WF)
(k : α) (v : β k) : m.contains k = false →
(m.insert k v).1.toList ~ ⟨k, v⟩ :: m.1.toList := by
simp_to_model using Perm.of_eq ∘ insertEntry_of_containsKey_eq_false

To spell it out explicitly: after simp_to_model, it should always be possible to generalize toListModel m.1.buckets = l so that m is then no longer present in the goal.

Comment on lines +719 to +726
open List in
theorem toList_insert_perm_of_not_mem [EquivBEq α] [LawfulHashable α]
(k : α) (v : β) (h' : ¬k ∈ m) :
(m.insert k v).toList ~ (k, v) :: m.toList := by
have t := DHashMap.toList_insert_perm_of_not_mem (β := fun _ => β) k v h'
simp at t
replace t := Perm.map (fun x : (_ : α) × β => (x.fst, x.snd)) t
simpa [Function.comp_def] using t
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way this is supposed to work is that you prove Const.toList_insert_perm_of_not_contains in Internal/RawLemmas.lean and DHashMap/(Raw)Lemmas.lean and then just apply that here. toList_inner and insert_inner should not exist.

To give more details:

  • I think you should drop Const.toListModel and change the statement of Const.toList_eq_toListModel to Raw.Const.toList m = (toListModel m.buckets).map (fun ⟨k, v⟩ => (k, v)).
  • Then you should add Raw.Const.toList_eq_toListModel to queryNames in Internal/RawLemmas.lean. Then you can add ← `(perm_of_perm ∘ List.Perm.map _) to congrNames (in addition to what was already added in my previous comment). This will allow you to put
namespace Const

variable {β : Type v} (m : Raw₀ α (fun _ => β))

open _root_.List in
theorem Const.toList_insert_perm_of_not_contains [EquivBEq α] [LawfulHashable α] (h : m.1.WF) {k : α} {v : β} :
    m.contains k = false → Raw.Const.toList (m.insert k v).1 ~ (k, v) :: (Raw.Const.toList m.1) := by
  simp_to_model
  exact fun h => by simp [insertEntry_of_containsKey_eq_false h]

end Const

in the bottom of Internal/RawLemmas.lean, from which the statements about (D)HashMap.toList follow imediately.

I should add that this still isn't perfect; it would be even better to prove containsKey k l = false → List.map (fun x => (x.fst, x.snd)) (insertEntry k v l) = (k, v) :: List.map (fun x => (x.fst, x.snd)) l in List/Associative.lean (perhaps as part of the theory of a "toListOfPairs" function) instead of inlining the proof.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants