From d28319d0118dd616166c3f5fd77f4ad72608daf9 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 19 Nov 2025 19:48:33 +0100 Subject: [PATCH 01/72] push work so far --- src/Std/Data/DHashMap/Internal/Defs.lean | 4 ++ src/Std/Data/DHashMap/Internal/RawLemmas.lean | 65 +++++++++++++++++++ src/Std/Data/DHashMap/Raw.lean | 11 ---- src/Std/Data/DHashMap/RawDef.lean | 12 ++++ src/Std/Data/DHashMap/RawLemmas.lean | 1 - src/Std/Data/Internal/List/Associative.lean | 30 +++++++++ 6 files changed, 111 insertions(+), 12 deletions(-) diff --git a/src/Std/Data/DHashMap/Internal/Defs.lean b/src/Std/Data/DHashMap/Internal/Defs.lean index effe67fb01a6..b28de4220102 100644 --- a/src/Std/Data/DHashMap/Internal/Defs.lean +++ b/src/Std/Data/DHashMap/Internal/Defs.lean @@ -480,6 +480,10 @@ def interSmaller [BEq α] [Hashable α] (m₁ : Raw₀ α β) (m₂ : Raw α β) def inter [BEq α] [Hashable α] (m₁ m₂ : Raw₀ α β) : Raw₀ α β := if m₁.1.size ≤ m₂.1.size then m₁.filter fun k _ => m₂.contains k else interSmaller m₁ m₂ +/-- Internal implementation detail of the hash map -/ +def checkBEq [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] (m₁ m₂ : Raw₀ α β) : Bool := + if m₁.1.size ≠ m₂.1.size then false else m₁.1.all (fun k v => m₂.get? k == some v) + section variable {β : Type v} diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index bf06ebae396d..922237a3ce73 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -11,6 +11,7 @@ import all Std.Data.DHashMap.Internal.Defs public import Std.Data.DHashMap.Internal.WF import all Std.Data.DHashMap.Raw import all Std.Data.DHashMap.Basic +import all Std.Data.DHashMap.RawDef meta import Std.Data.DHashMap.Basic public section @@ -2595,6 +2596,70 @@ end Const end insertMany +section BEq +variable {m₁ m₂ : Raw₀ α β} + +theorem checkBEq_eq_true_of_Equiv {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : m₁.1.Equiv m₂.1 → checkBEq m₁ m₂ := by + rw [checkBEq] + intro hyp + split + case isTrue hs => + revert hyp hs + simp_to_model [Equiv, size] + intro hp hne + have := List.Perm.length_eq hp + contradiction + case isFalse hs => + rw [all_eq_true] + · simp only [ne_eq, Decidable.not_not] at hs + revert hyp hs + simp_to_model [Equiv, size, get?, get] + intro hp _ a h + rw [contains_eq_containsKey] at h + · apply beq_of_eq + rw [← getValueCast?_eq_some_getValueCast] + exact getValueCast?_of_perm (by wf_trivial) (List.Perm.symm hp) + · wf_trivial + · wf_trivial + +theorem Equiv_of_checkBEq_eq_true {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : checkBEq m₁ m₂ → m₁.1.Equiv m₂.1 := by + intro hyp + rw [checkBEq] at hyp + split at hyp + case isTrue => contradiction + case isFalse hs => + simp at hs + rw [all_eq_true] at hyp + · revert hyp hs + simp_to_model [contains, get?, get, Equiv, size] + intro hyp hs + apply getValueCast?_ext (by wf_trivial) (by wf_trivial) + intro a + by_cases hc : containsKey a (toListModel m₁.val.buckets) + case neg => + have sub : ∀ a : α, containsKey a (toListModel m₁.val.buckets) → containsKey a (toListModel m₂.val.buckets) := by + intro a mem + specialize hyp a mem + replace hyp := eq_of_beq hyp + apply List.containsKey_of_getValueCast?_eq_some hyp + simp only [Bool.not_eq_true] at hc + rw [getValueCast?_eq_none hc] + symm + sorry + case pos => + specialize hyp a hc + replace hyp := eq_of_beq hyp + rw [hyp] + rw [getValueCast?_eq_some_getValueCast hc] + + + + + · wf_trivial + + +end BEq + section Union variable (m₁ m₂ : Raw₀ α β) diff --git a/src/Std/Data/DHashMap/Raw.lean b/src/Std/Data/DHashMap/Raw.lean index fbdc6ea5a584..bd08a15ce10f 100644 --- a/src/Std/Data/DHashMap/Raw.lean +++ b/src/Std/Data/DHashMap/Raw.lean @@ -476,17 +476,6 @@ only those mappings where the function returns `some` value. @[inline] def keysArray (m : Raw α β) : Array α := m.fold (fun acc k _ => acc.push k) (.emptyWithCapacity m.size) -/-- Checks if all elements satisfy the predicate, short-circuiting if a predicate fails. -/ -@[inline] def all (m : Raw α β) (p : (a : α) → β a → Bool) : Bool := Id.run do - for a in m do - if ¬ p a.1 a.2 then return false - return true - -/-- Checks if any element satisfies the predicate, short-circuiting if a predicate succeeds. -/ -@[inline] def any (m : Raw α β) (p : (a : α) → β a → Bool) : Bool := Id.run do - for a in m do - if p a.1 a.2 then return true - return false /-- Computes the union of the given hash maps. If a key appears in both maps, the entry contained in the second argument will appear in the result. diff --git a/src/Std/Data/DHashMap/RawDef.lean b/src/Std/Data/DHashMap/RawDef.lean index f17b03f1c739..5d033f0cb342 100644 --- a/src/Std/Data/DHashMap/RawDef.lean +++ b/src/Std/Data/DHashMap/RawDef.lean @@ -81,6 +81,18 @@ instance x : ForM m (Raw α β) ((a : α) × β a) where instance : ForIn m (Raw α β) ((a : α) × β a) where forIn m init f := m.forIn (fun a b acc => f ⟨a, b⟩ acc) init +/-- Checks if all elements satisfy the predicate, short-circuiting if a predicate fails. -/ +@[inline] def all (m : Raw α β) (p : (a : α) → β a → Bool) : Bool := Id.run do + for a in m do + if ¬ p a.1 a.2 then return false + return true + +/-- Checks if any element satisfies the predicate, short-circuiting if a predicate succeeds. -/ +@[inline] def any (m : Raw α β) (p : (a : α) → β a → Bool) : Bool := Id.run do + for a in m do + if p a.1 a.2 then return true + return false + end Raw end Std.DHashMap diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index e24813fcd59c..ab94456b5d58 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -9,7 +9,6 @@ prelude public import Std.Data.DHashMap.Internal.Raw public import Std.Data.DHashMap.Internal.RawLemmas import all Std.Data.DHashMap.Raw - public section /-! diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 1de4b9d3f097..399a942bb678 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -3571,6 +3571,36 @@ theorem insertList_insertEntry_right_equiv_insertEntry_insertList [BEq α] [Equi . simp only [Option.some_or] . rw [@getEntry?_insertList α β _ _ l toInsert distinct_l (DistinctKeys_impl_Pairwise_distinct distinct_toInsert) a] +theorem length_le_of_keys_subset [BEq α] [EquivBEq α] + {l₁ l₂ : List ((a : α) × β a)} + (dl₁ : DistinctKeys l₁) + (dl₂ : DistinctKeys l₂) + (h : ∀ a, containsKey a l₁ → containsKey a l₂) : + l₁.length ≤ l₂.length := by + induction l₁ generalizing l₂ with + | nil => simp + | cons hd tl ih => + have hc := h hd.1 (by rw [containsKey_cons_self]) + sorry + +theorem containsKey_lemma [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : α) × β a)} (dl₁ : DistinctKeys l₁) (dl₂ : DistinctKeys l₂) (hl : l₂.length = l₁.length) (hs : ∀ (a : α), containsKey a l₁ → containsKey a l₂) : ∀ (a : α), containsKey a l₂ → containsKey a l₁ := by + intro a ha + apply Classical.byContradiction + intro hb + simp at hb + suffices l₁.length < l₂.length by omega + suffices l₁.length ≤ (eraseKey a l₂).length ∧ 1 + (eraseKey a l₂).length = l₂.length by omega + apply And.intro + · apply length_le_of_keys_subset dl₁ (DistinctKeys.eraseKey dl₂) + intro a₂ mem₂ + sorry + · simp only [length_eraseKey, ha, ↓reduceIte] + have : l₂.length > 0 := by + cases l₂ + · simp at ha + · simp + omega + section variable {β : Type v} From fc9c400212c6a59fc4f040500eb092e898e3a69f Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 19 Nov 2025 20:01:16 +0100 Subject: [PATCH 02/72] Sublemma works --- src/Std/Data/Internal/List/Associative.lean | 30 ++++++++++++++++++++- src/lake/tests/clone/hello | 1 + src/lake/tests/depTree/a | 1 + src/lake/tests/depTree/b | 1 + src/lake/tests/depTree/c | 1 + src/lake/tests/depTree/d | 1 + src/lake/tests/manifest/bar | 1 + src/lake/tests/packageOverrides/bar1 | 1 + 8 files changed, 36 insertions(+), 1 deletion(-) create mode 160000 src/lake/tests/clone/hello create mode 160000 src/lake/tests/depTree/a create mode 160000 src/lake/tests/depTree/b create mode 160000 src/lake/tests/depTree/c create mode 160000 src/lake/tests/depTree/d create mode 160000 src/lake/tests/manifest/bar create mode 160000 src/lake/tests/packageOverrides/bar1 diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 399a942bb678..960ee85e9c68 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -3581,7 +3581,35 @@ theorem length_le_of_keys_subset [BEq α] [EquivBEq α] | nil => simp | cons hd tl ih => have hc := h hd.1 (by rw [containsKey_cons_self]) - sorry + suffices tl.length ≤ (eraseKey hd.1 l₂).length by + rw [List.length_eraseKey, hc] at this + simp at this + simp + have : l₂.length > 0 := by + cases l₂ + case nil => simp at hc + case cons => simp + omega + apply ih + · rw [List.distinctKeys_cons_iff] at dl₁ + exact dl₁.1 + · exact DistinctKeys.eraseKey dl₂ + · intro a mem + rw [containsKey_eraseKey] + · simp only [Bool.and_eq_true, Bool.not_eq_eq_eq_not, Bool.not_true] + apply And.intro + · rw [List.distinctKeys_cons_iff] at dl₁ + apply Classical.byContradiction + intro hyp + simp only [Bool.not_eq_false] at hyp + rw [containsKey_congr hyp] at dl₁ + rw [dl₁.2] at mem + contradiction + · specialize h a + rw [containsKey_cons] at h + apply h + simp [mem] + · exact dl₂ theorem containsKey_lemma [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : α) × β a)} (dl₁ : DistinctKeys l₁) (dl₂ : DistinctKeys l₂) (hl : l₂.length = l₁.length) (hs : ∀ (a : α), containsKey a l₁ → containsKey a l₂) : ∀ (a : α), containsKey a l₂ → containsKey a l₁ := by intro a ha diff --git a/src/lake/tests/clone/hello b/src/lake/tests/clone/hello new file mode 160000 index 000000000000..3a924f941e40 --- /dev/null +++ b/src/lake/tests/clone/hello @@ -0,0 +1 @@ +Subproject commit 3a924f941e40846cc134b2c09c19ae71f4dbf9cd diff --git a/src/lake/tests/depTree/a b/src/lake/tests/depTree/a new file mode 160000 index 000000000000..5776f391d0eb --- /dev/null +++ b/src/lake/tests/depTree/a @@ -0,0 +1 @@ +Subproject commit 5776f391d0eb2e841041ebadc3f847d16bc1843a diff --git a/src/lake/tests/depTree/b b/src/lake/tests/depTree/b new file mode 160000 index 000000000000..f335505571b9 --- /dev/null +++ b/src/lake/tests/depTree/b @@ -0,0 +1 @@ +Subproject commit f335505571b9c41572d3b56511f454ceb73772ae diff --git a/src/lake/tests/depTree/c b/src/lake/tests/depTree/c new file mode 160000 index 000000000000..9f7bbb33a1c1 --- /dev/null +++ b/src/lake/tests/depTree/c @@ -0,0 +1 @@ +Subproject commit 9f7bbb33a1c18f4dc4733a3ba0ac338e867fb88d diff --git a/src/lake/tests/depTree/d b/src/lake/tests/depTree/d new file mode 160000 index 000000000000..32bf98fb6b71 --- /dev/null +++ b/src/lake/tests/depTree/d @@ -0,0 +1 @@ +Subproject commit 32bf98fb6b712f4096ecadd1cde3981897d5fd30 diff --git a/src/lake/tests/manifest/bar b/src/lake/tests/manifest/bar new file mode 160000 index 000000000000..977bed86d8e2 --- /dev/null +++ b/src/lake/tests/manifest/bar @@ -0,0 +1 @@ +Subproject commit 977bed86d8e2b00c59af7e8c7d0552969d0fcba9 diff --git a/src/lake/tests/packageOverrides/bar1 b/src/lake/tests/packageOverrides/bar1 new file mode 160000 index 000000000000..cc741410bf5f --- /dev/null +++ b/src/lake/tests/packageOverrides/bar1 @@ -0,0 +1 @@ +Subproject commit cc741410bf5f604dfbf2cded3cf70580e64c802a From 26bffd87dd1040a3aefb5401b5d957c51a6c4203 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 19 Nov 2025 20:06:05 +0100 Subject: [PATCH 03/72] Sublemma now works --- src/Std/Data/Internal/List/Associative.lean | 12 +++++++++++- src/lake/tests/clone/hello | 1 - src/lake/tests/depTree/a | 1 - src/lake/tests/depTree/b | 1 - src/lake/tests/depTree/c | 1 - src/lake/tests/depTree/d | 1 - src/lake/tests/manifest/bar | 1 - src/lake/tests/packageOverrides/bar1 | 1 - 8 files changed, 11 insertions(+), 8 deletions(-) delete mode 160000 src/lake/tests/clone/hello delete mode 160000 src/lake/tests/depTree/a delete mode 160000 src/lake/tests/depTree/b delete mode 160000 src/lake/tests/depTree/c delete mode 160000 src/lake/tests/depTree/d delete mode 160000 src/lake/tests/manifest/bar delete mode 160000 src/lake/tests/packageOverrides/bar1 diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 960ee85e9c68..4b4651a019d2 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -3621,7 +3621,17 @@ theorem containsKey_lemma [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : α) × apply And.intro · apply length_le_of_keys_subset dl₁ (DistinctKeys.eraseKey dl₂) intro a₂ mem₂ - sorry + rw [containsKey_eraseKey dl₂] + simp only [Bool.and_eq_true, Bool.not_eq_eq_eq_not, Bool.not_true] + apply And.intro + · apply Classical.byContradiction + intro hyp + simp only [Bool.not_eq_false] at hyp + rw [containsKey_congr hyp] at hb + rw [hb] at mem₂ + contradiction + · apply hs + exact mem₂ · simp only [length_eraseKey, ha, ↓reduceIte] have : l₂.length > 0 := by cases l₂ diff --git a/src/lake/tests/clone/hello b/src/lake/tests/clone/hello deleted file mode 160000 index 3a924f941e40..000000000000 --- a/src/lake/tests/clone/hello +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3a924f941e40846cc134b2c09c19ae71f4dbf9cd diff --git a/src/lake/tests/depTree/a b/src/lake/tests/depTree/a deleted file mode 160000 index 5776f391d0eb..000000000000 --- a/src/lake/tests/depTree/a +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5776f391d0eb2e841041ebadc3f847d16bc1843a diff --git a/src/lake/tests/depTree/b b/src/lake/tests/depTree/b deleted file mode 160000 index f335505571b9..000000000000 --- a/src/lake/tests/depTree/b +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f335505571b9c41572d3b56511f454ceb73772ae diff --git a/src/lake/tests/depTree/c b/src/lake/tests/depTree/c deleted file mode 160000 index 9f7bbb33a1c1..000000000000 --- a/src/lake/tests/depTree/c +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9f7bbb33a1c18f4dc4733a3ba0ac338e867fb88d diff --git a/src/lake/tests/depTree/d b/src/lake/tests/depTree/d deleted file mode 160000 index 32bf98fb6b71..000000000000 --- a/src/lake/tests/depTree/d +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 32bf98fb6b712f4096ecadd1cde3981897d5fd30 diff --git a/src/lake/tests/manifest/bar b/src/lake/tests/manifest/bar deleted file mode 160000 index 977bed86d8e2..000000000000 --- a/src/lake/tests/manifest/bar +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 977bed86d8e2b00c59af7e8c7d0552969d0fcba9 diff --git a/src/lake/tests/packageOverrides/bar1 b/src/lake/tests/packageOverrides/bar1 deleted file mode 160000 index cc741410bf5f..000000000000 --- a/src/lake/tests/packageOverrides/bar1 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cc741410bf5f604dfbf2cded3cf70580e64c802a From d586c3f25b7bd541f0b60b2ddab147551c01631b Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 19 Nov 2025 20:13:14 +0100 Subject: [PATCH 04/72] Main lemma goes through --- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 28 ++++++++++--------- src/Std/Data/Internal/List/Associative.lean | 2 +- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 922237a3ce73..b81571ee8f1d 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -2637,24 +2637,26 @@ theorem Equiv_of_checkBEq_eq_true {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF intro a by_cases hc : containsKey a (toListModel m₁.val.buckets) case neg => - have sub : ∀ a : α, containsKey a (toListModel m₁.val.buckets) → containsKey a (toListModel m₂.val.buckets) := by - intro a mem - specialize hyp a mem - replace hyp := eq_of_beq hyp - apply List.containsKey_of_getValueCast?_eq_some hyp - simp only [Bool.not_eq_true] at hc - rw [getValueCast?_eq_none hc] - symm - sorry + by_cases heq : containsKey a (toListModel m₂.val.buckets) + case pos => + have sub : ∀ a : α, containsKey a (toListModel m₁.val.buckets) → containsKey a (toListModel m₂.val.buckets) := by + intro a mem + specialize hyp a mem + replace hyp := eq_of_beq hyp + apply List.containsKey_of_getValueCast?_eq_some hyp + simp only [Bool.not_eq_true] at hc + rw [getValueCast?_eq_none hc] + symm + rw [@containsKey_of_subset_of_length_eq _ _ _ _ _ _ (by wf_trivial) (by wf_trivial) hs.symm sub a heq] at hc + contradiction + case neg => + simp only [Bool.not_eq_true] at heq hc + rw [getValueCast?_eq_none heq, getValueCast?_eq_none hc] case pos => specialize hyp a hc replace hyp := eq_of_beq hyp rw [hyp] rw [getValueCast?_eq_some_getValueCast hc] - - - - · wf_trivial diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 4b4651a019d2..ca1fd5e75e8d 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -3611,7 +3611,7 @@ theorem length_le_of_keys_subset [BEq α] [EquivBEq α] simp [mem] · exact dl₂ -theorem containsKey_lemma [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : α) × β a)} (dl₁ : DistinctKeys l₁) (dl₂ : DistinctKeys l₂) (hl : l₂.length = l₁.length) (hs : ∀ (a : α), containsKey a l₁ → containsKey a l₂) : ∀ (a : α), containsKey a l₂ → containsKey a l₁ := by +theorem containsKey_of_subset_of_length_eq [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : α) × β a)} (dl₁ : DistinctKeys l₁) (dl₂ : DistinctKeys l₂) (hl : l₂.length = l₁.length) (hs : ∀ (a : α), containsKey a l₁ → containsKey a l₂) : ∀ (a : α), containsKey a l₂ → containsKey a l₁ := by intro a ha apply Classical.byContradiction intro hb From ae7a4ace9470f64bff6832e411039530b4b7ece6 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 19 Nov 2025 20:29:03 +0100 Subject: [PATCH 05/72] Add first user-facing lemmas --- src/Std/Data/DHashMap/Basic.lean | 3 +++ src/Std/Data/DHashMap/Internal/RawLemmas.lean | 1 - src/Std/Data/DHashMap/Lemmas.lean | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Std/Data/DHashMap/Basic.lean b/src/Std/Data/DHashMap/Basic.lean index 88abac99b4f6..c15e5ff58311 100644 --- a/src/Std/Data/DHashMap/Basic.lean +++ b/src/Std/Data/DHashMap/Basic.lean @@ -349,6 +349,9 @@ This function always iterates through the smaller map, so the expected runtime i instance [BEq α] [Hashable α] : Union (DHashMap α β) := ⟨union⟩ instance [BEq α] [Hashable α] : Inter (DHashMap α β) := ⟨inter⟩ +instance [LawfulBEq α] [∀ k, BEq (β k)] : BEq (DHashMap α β) where + beq a b := Raw₀.checkBEq ⟨a.1, a.2.size_buckets_pos⟩ ⟨b.1, b.2.size_buckets_pos⟩ + section Unverified /-! We currently do not provide lemmas for the functions below. -/ diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index b81571ee8f1d..315c37249ef0 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -2659,7 +2659,6 @@ theorem Equiv_of_checkBEq_eq_true {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF rw [getValueCast?_eq_some_getValueCast hc] · wf_trivial - end BEq section Union diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index 7e63f8a5397c..cd5aa9051caf 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -1838,6 +1838,21 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] {l : ρ} : (m.insertMany l).isEmpty → m.isEmpty := Raw₀.isEmpty_of_isEmpty_insertMany ⟨m.1, _⟩ m.2 +section BEq +variable {m₁ m₂ : DHashMap α β} [LawfulBEq α] [∀ k, BEq (β k)] + +theorem BEq_of_Equiv [∀ k, ReflBEq (β k)] (h : m₁ ~m m₂ ) : m₁ == m₂ := by + simp [BEq.beq] + apply Raw₀.checkBEq_eq_true_of_Equiv m₁.2 m₂.2 h.1 + +theorem Equiv.of_BEq [∀ k, LawfulBEq (β k)] (h : m₁ == m₂) : m₁ ~m m₂ := by + constructor + have := @Raw₀.Equiv_of_checkBEq_eq_true α β _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 _ _ _ h + simp only at this + exact this + +end BEq + section Union variable (m₁ m₂ : DHashMap α β) From 54f89f9e51bd9600479530c1e84135a49db0b110 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 20 Nov 2025 19:40:48 +0000 Subject: [PATCH 06/72] Add working model lemma --- src/Std/Data/DHashMap/Basic.lean | 2 +- src/Std/Data/DHashMap/Internal/Defs.lean | 2 +- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 22 ++++--------- src/Std/Data/DHashMap/Internal/WF.lean | 32 +++++++++++++++++++ src/Std/Data/Internal/List/Associative.lean | 4 +++ 5 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/Std/Data/DHashMap/Basic.lean b/src/Std/Data/DHashMap/Basic.lean index c15e5ff58311..8845ffa38bd9 100644 --- a/src/Std/Data/DHashMap/Basic.lean +++ b/src/Std/Data/DHashMap/Basic.lean @@ -350,7 +350,7 @@ instance [BEq α] [Hashable α] : Union (DHashMap α β) := ⟨union⟩ instance [BEq α] [Hashable α] : Inter (DHashMap α β) := ⟨inter⟩ instance [LawfulBEq α] [∀ k, BEq (β k)] : BEq (DHashMap α β) where - beq a b := Raw₀.checkBEq ⟨a.1, a.2.size_buckets_pos⟩ ⟨b.1, b.2.size_buckets_pos⟩ + beq a b := Raw₀.beq ⟨a.1, a.2.size_buckets_pos⟩ ⟨b.1, b.2.size_buckets_pos⟩ section Unverified diff --git a/src/Std/Data/DHashMap/Internal/Defs.lean b/src/Std/Data/DHashMap/Internal/Defs.lean index b28de4220102..7b0a151a85f3 100644 --- a/src/Std/Data/DHashMap/Internal/Defs.lean +++ b/src/Std/Data/DHashMap/Internal/Defs.lean @@ -481,7 +481,7 @@ def inter [BEq α] [Hashable α] (m₁ m₂ : Raw₀ α β) : Raw₀ α β := if m₁.1.size ≤ m₂.1.size then m₁.filter fun k _ => m₂.contains k else interSmaller m₁ m₂ /-- Internal implementation detail of the hash map -/ -def checkBEq [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] (m₁ m₂ : Raw₀ α β) : Bool := +def beq [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] (m₁ m₂ : Raw₀ α β) : Bool := if m₁.1.size ≠ m₂.1.size then false else m₁.1.all (fun k v => m₂.get? k == some v) section diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 315c37249ef0..4eee50ee489b 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -163,6 +163,7 @@ private meta def queryMap : Std.DHashMap Name (fun _ => Name × Array (MacroM (T ⟨`getEntryD, (``getEntryD_eq_getEntryD, #[`(getEntryD_of_perm _)])⟩, ⟨`getEntry!, (``getEntry!_eq_getEntry!, #[`(getEntry!_of_perm _)])⟩, ⟨`toList, (``Raw.toList_eq_toListModel, #[])⟩, + ⟨`beq, (``toListModel_beq, #[])⟩, ⟨`keys, (``Raw.keys_eq_keys_toListModel, #[`(perm_keys_congr_left)])⟩, ⟨`Const.toList, (``Raw.Const.toList_eq_toListModel_map, #[`(perm_map_congr_left)])⟩, ⟨`foldM, (``Raw.foldM_eq_foldlM_toListModel, #[])⟩, @@ -1452,17 +1453,8 @@ theorem any_eq_false [LawfulBEq α] {p : (a : α) → β a → Bool} (h : m.1.WF omit [Hashable α] [BEq α] in theorem all_toList {p : (a : α) → β a → Bool} : - m.1.toList.all (fun x => p x.1 x.2) = m.1.all p := by - simp only [Raw.all, ForIn.forIn, Bool.not_eq_true, bind_pure_comp, map_pure, Id.run_bind] - rw [forIn_eq_forIn_toList, forIn_eq_forIn'] - induction m.val.toList with - | nil => simp - | cons hd tl ih => - simp only [forIn'_eq_forIn, List.all_cons] - by_cases h : p hd.fst hd.snd = false - · simp [h] - · simp only [forIn'_eq_forIn] at ih - simp [h, ih] + m.1.toList.all (fun x => p x.1 x.2) = m.1.all p := + DHashMap.Internal.Raw.all_toList omit [Hashable α] [BEq α] in theorem all_eq_not_any_not {p : (a : α) → β a → Bool} : @@ -2599,8 +2591,8 @@ end insertMany section BEq variable {m₁ m₂ : Raw₀ α β} -theorem checkBEq_eq_true_of_Equiv {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : m₁.1.Equiv m₂.1 → checkBEq m₁ m₂ := by - rw [checkBEq] +theorem checkBEq_eq_true_of_Equiv {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : m₁.1.Equiv m₂.1 → beq m₁ m₂ := by + rw [beq] intro hyp split case isTrue hs => @@ -2622,9 +2614,9 @@ theorem checkBEq_eq_true_of_Equiv {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF · wf_trivial · wf_trivial -theorem Equiv_of_checkBEq_eq_true {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : checkBEq m₁ m₂ → m₁.1.Equiv m₂.1 := by +theorem Equiv_of_checkBEq_eq_true {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : beq m₁ m₂ → m₁.1.Equiv m₂.1 := by intro hyp - rw [checkBEq] at hyp + rw [beq] at hyp split at hyp case isTrue => contradiction case isFalse hs => diff --git a/src/Std/Data/DHashMap/Internal/WF.lean b/src/Std/Data/DHashMap/Internal/WF.lean index 9d7db379b4cb..97285e39d93a 100644 --- a/src/Std/Data/DHashMap/Internal/WF.lean +++ b/src/Std/Data/DHashMap/Internal/WF.lean @@ -275,6 +275,19 @@ theorem forIn_eq_forIn_toListModel {δ : Type w} {l : Raw α β} {m : Type w → · simp · simpa using ih' +theorem all_toList {p : (a : α) → β a → Bool} {m : Raw α β}: + m.toList.all (fun x => p x.1 x.2) = m.all p := by + simp only [Raw.all, ForIn.forIn, Bool.not_eq_true, bind_pure_comp, map_pure, Id.run_bind] + rw [forIn_eq_forIn_toListModel, ← toList_eq_toListModel, forIn_eq_forIn'] + induction m.toList with + | nil => simp only [all_nil, forIn'_nil, Id.run_pure] + | cons hd tl ih => + simp only [forIn'_eq_forIn, List.all_cons] + by_cases h : p hd.fst hd.snd = false + · simp [h] + · simp only [forIn'_eq_forIn] at ih + simp [h, ih] + end Raw namespace Raw₀ @@ -1487,4 +1500,23 @@ theorem Const.wf_insertManyIfNewUnit₀ [BEq α] [Hashable α] [EquivBEq α] [La {l : ρ} (h' : m.WF) : (Const.insertManyIfNewUnit ⟨m, h⟩ l).1.1.WF := (Raw₀.Const.insertManyIfNewUnit ⟨m, h⟩ l).2 _ Raw.WF.insertIfNew₀ h' +theorem toListModel_beq [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] {m₁ m₂ : Raw₀ α β} (h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) : + beq m₁ m₂ = beqModel m₁.1.toList m₂.1.toList := by + rw [beq, beqModel] + split + case isTrue h => + rw [Raw.size_eq_length, Raw.size_eq_length] at h + rw [Raw.toList_eq_toListModel, Raw.toList_eq_toListModel] + · simp only [ne_eq, h, not_false_eq_true, ↓reduceIte] + · exact h₂ + · exact h₁ + case isFalse h => + rw [Raw.size_eq_length, Raw.size_eq_length] at h + simp [Raw.toList_eq_toListModel, h, ← Raw.all_toList] + congr + · ext x + rw [get?_eq_getValueCast? h₂] + · exact h₂ + · exact h₁ + end Raw₀ diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index ca1fd5e75e8d..0e8299a0315c 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -257,6 +257,10 @@ end | ⟨k, v⟩ :: l => if h : k == a then some (cast (congrArg β (eq_of_beq h)) v) else getValueCast? a l +/-- Internal implementation detail of the hash map -/ +def beqModel [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] (l₁ l₂ : List ((a : α) × β a)) := + if l₁.length ≠ l₂.length then false else (l₁.all fun x => getValueCast? x.fst l₂ == some x.snd) + @[simp] theorem getValueCast?_nil [BEq α] [LawfulBEq α] {a : α} : getValueCast? a ([] : List ((a : α) × β a)) = none := rfl theorem getValueCast?_cons [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} : From 9b0035c34cd48b77b823cd8e3cc7c8ee1e311bb7 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 20 Nov 2025 21:31:42 +0000 Subject: [PATCH 07/72] Work on the train --- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 22 +------ src/Std/Data/Internal/List/Associative.lean | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 4eee50ee489b..de8825bfcfb4 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -2592,27 +2592,7 @@ section BEq variable {m₁ m₂ : Raw₀ α β} theorem checkBEq_eq_true_of_Equiv {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : m₁.1.Equiv m₂.1 → beq m₁ m₂ := by - rw [beq] - intro hyp - split - case isTrue hs => - revert hyp hs - simp_to_model [Equiv, size] - intro hp hne - have := List.Perm.length_eq hp - contradiction - case isFalse hs => - rw [all_eq_true] - · simp only [ne_eq, Decidable.not_not] at hs - revert hyp hs - simp_to_model [Equiv, size, get?, get] - intro hp _ a h - rw [contains_eq_containsKey] at h - · apply beq_of_eq - rw [← getValueCast?_eq_some_getValueCast] - exact getValueCast?_of_perm (by wf_trivial) (List.Perm.symm hp) - · wf_trivial - · wf_trivial + simp_to_model using List.beqModel_eq_true_of_perm theorem Equiv_of_checkBEq_eq_true {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : beq m₁ m₂ → m₁.1.Equiv m₂.1 := by intro hyp diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 0e8299a0315c..3a105851572f 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -6699,6 +6699,63 @@ theorem isEmpty_filter_key_iff [BEq α] [EquivBEq α] {f : α → Bool} simp only [getKey, getKey?_eq_getEntry?, this] at h exact h +theorem beqModel_eq_true_of_perm [BEq α] [Hashable α] [LawfulBEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → beqModel l₁ l₂ := by + intro hyp + rw [beqModel] + split + case isTrue hlen => + rw [ne_eq] at hlen + apply Classical.byContradiction + intro _ + exact hlen <| List.Perm.length_eq hyp + case isFalse hlen => + simp only [List.all_eq_true] + intro ⟨k,v⟩ mem + have hv := getValueCast_of_mem mem hl₁ + have hc := containsKey_of_mem mem + apply beq_of_eq + simp only at |- hc hv + rw [← hv, ← getValueCast?_eq_some_getValueCast] + symm + apply getValueCast?_of_perm hl₁ hyp + +theorem perm_of_beqModel [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : + beqModel l₁ l₂ → l₁.Perm l₂ := by + rw [beqModel] + split + case isTrue => intro; contradiction + case isFalse he => + simp only [ne_eq, Decidable.not_not] at he + simp only [List.all_eq_true, beq_iff_eq] + intro hyp + apply getValueCast?_ext hl₁ hl₂ + intro a + have hyp2 : ∀ (a : α), (getValueCast? a l₂ == getValueCast? a l₁) = true := by + intro k + by_cases hc : containsKey k l₁ + case pos => + sorry + by_cases hc₁ : containsKey a l₁ + case pos => + apply eq_of_beq + apply BEq.symm + apply hyp2 + case neg => + rw [Bool.not_eq_true] at hc₁ + by_cases hc₂ : containsKey a l₂ + case pos => + suffices (∀ (a : α), containsKey a l₁ = true → containsKey a l₂ = true) by + rw [@containsKey_of_subset_of_length_eq α β _ _ l₁ l₂ hl₁ hl₂ he.symm this a hc₂] at hc₁ + contradiction + intro k' mem + have := eq_of_beq <| hyp2 k' + rw [getValueCast?_eq_some_getValueCast mem] at this + apply List.containsKey_of_getValueCast?_eq_some + exact this + case neg => + rw [Bool.not_eq_true] at hc₂ + rw [getValueCast?_eq_none hc₁, getValueCast?_eq_none hc₂] + namespace Const theorem getKey_getValue_mem [BEq α] [EquivBEq α] {β : Type v} {l : List ((_ : α) × β)} {k : α} {h} : From a560481d81c466ddda29affe273306a7e2efe01e Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 20 Nov 2025 23:14:09 +0000 Subject: [PATCH 08/72] Lemmas go through --- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 36 +------------------ src/Std/Data/Internal/List/Associative.lean | 16 +++++---- 2 files changed, 11 insertions(+), 41 deletions(-) diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index de8825bfcfb4..542b19512dd1 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -2595,41 +2595,7 @@ theorem checkBEq_eq_true_of_Equiv {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF simp_to_model using List.beqModel_eq_true_of_perm theorem Equiv_of_checkBEq_eq_true {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : beq m₁ m₂ → m₁.1.Equiv m₂.1 := by - intro hyp - rw [beq] at hyp - split at hyp - case isTrue => contradiction - case isFalse hs => - simp at hs - rw [all_eq_true] at hyp - · revert hyp hs - simp_to_model [contains, get?, get, Equiv, size] - intro hyp hs - apply getValueCast?_ext (by wf_trivial) (by wf_trivial) - intro a - by_cases hc : containsKey a (toListModel m₁.val.buckets) - case neg => - by_cases heq : containsKey a (toListModel m₂.val.buckets) - case pos => - have sub : ∀ a : α, containsKey a (toListModel m₁.val.buckets) → containsKey a (toListModel m₂.val.buckets) := by - intro a mem - specialize hyp a mem - replace hyp := eq_of_beq hyp - apply List.containsKey_of_getValueCast?_eq_some hyp - simp only [Bool.not_eq_true] at hc - rw [getValueCast?_eq_none hc] - symm - rw [@containsKey_of_subset_of_length_eq _ _ _ _ _ _ (by wf_trivial) (by wf_trivial) hs.symm sub a heq] at hc - contradiction - case neg => - simp only [Bool.not_eq_true] at heq hc - rw [getValueCast?_eq_none heq, getValueCast?_eq_none hc] - case pos => - specialize hyp a hc - replace hyp := eq_of_beq hyp - rw [hyp] - rw [getValueCast?_eq_some_getValueCast hc] - · wf_trivial + simp_to_model using List.perm_of_beqModel end BEq diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 3a105851572f..7c89cfc6a00f 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -6730,16 +6730,20 @@ theorem perm_of_beqModel [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k intro hyp apply getValueCast?_ext hl₁ hl₂ intro a - have hyp2 : ∀ (a : α), (getValueCast? a l₂ == getValueCast? a l₁) = true := by - intro k - by_cases hc : containsKey k l₁ - case pos => - sorry + have hyp2 : ∀ (a : α) (h : containsKey a l₁), (getValueCast? a l₂ == getValueCast? a l₁) = true := by + intro a mem + rw [getValueCast?_eq_some_getValueCast mem] + apply beq_of_eq + specialize hyp ⟨a, getValueCast a l₁ mem⟩ + specialize hyp (by apply List.getValueCast_mem) + simp only at hyp + rw [hyp] by_cases hc₁ : containsKey a l₁ case pos => apply eq_of_beq apply BEq.symm apply hyp2 + exact hc₁ case neg => rw [Bool.not_eq_true] at hc₁ by_cases hc₂ : containsKey a l₂ @@ -6748,7 +6752,7 @@ theorem perm_of_beqModel [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k rw [@containsKey_of_subset_of_length_eq α β _ _ l₁ l₂ hl₁ hl₂ he.symm this a hc₂] at hc₁ contradiction intro k' mem - have := eq_of_beq <| hyp2 k' + have := eq_of_beq <| hyp2 k' mem rw [getValueCast?_eq_some_getValueCast mem] at this apply List.containsKey_of_getValueCast?_eq_some exact this From 44f93984034ad38e2a0dc0ca0c4da9273d7c41fa Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 26 Nov 2025 11:52:19 +0000 Subject: [PATCH 09/72] Progress with the const BEq --- src/Std/Data/DHashMap/Internal/Defs.lean | 4 ++ src/Std/Data/DHashMap/Internal/RawLemmas.lean | 20 +++++++-- src/Std/Data/DHashMap/Internal/WF.lean | 19 +++++++++ src/Std/Data/DHashMap/Lemmas.lean | 8 ++-- src/Std/Data/Internal/List/Associative.lean | 41 +++++++++++++++++++ 5 files changed, 85 insertions(+), 7 deletions(-) diff --git a/src/Std/Data/DHashMap/Internal/Defs.lean b/src/Std/Data/DHashMap/Internal/Defs.lean index 7b0a151a85f3..0bdf55378842 100644 --- a/src/Std/Data/DHashMap/Internal/Defs.lean +++ b/src/Std/Data/DHashMap/Internal/Defs.lean @@ -494,6 +494,10 @@ def Const.get? [BEq α] [Hashable α] (m : Raw₀ α (fun _ => β)) (a : α) : O let ⟨i, h⟩ := mkIdx buckets.size h (hash a) buckets[i].get? a +/-- Internal implementation detail of the hash map -/ +def Const.beq [BEq α] [Hashable α] [BEq β] (m₁ m₂ : Raw₀ α (fun _ => β)) : Bool := + if m₁.1.size ≠ m₂.1.size then false else m₁.1.all (fun k v => Const.get? m₂ k == some v) + /-- Internal implementation detail of the hash map -/ def Const.get [BEq α] [Hashable α] (m : Raw₀ α (fun _ => β)) (a : α) (hma : m.contains a) : β := diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 542b19512dd1..46d4d4a1ae16 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -163,6 +163,7 @@ private meta def queryMap : Std.DHashMap Name (fun _ => Name × Array (MacroM (T ⟨`getEntryD, (``getEntryD_eq_getEntryD, #[`(getEntryD_of_perm _)])⟩, ⟨`getEntry!, (``getEntry!_eq_getEntry!, #[`(getEntry!_of_perm _)])⟩, ⟨`toList, (``Raw.toList_eq_toListModel, #[])⟩, + ⟨`Const.beq, (``Raw₀.Const.toListModel_beq, #[])⟩, ⟨`beq, (``toListModel_beq, #[])⟩, ⟨`keys, (``Raw.keys_eq_keys_toListModel, #[`(perm_keys_congr_left)])⟩, ⟨`Const.toList, (``Raw.Const.toList_eq_toListModel_map, #[`(perm_map_congr_left)])⟩, @@ -2589,16 +2590,29 @@ end Const end insertMany section BEq -variable {m₁ m₂ : Raw₀ α β} +variable {m₁ m₂ : Raw₀ α β} [LawfulBEq α] [∀ k, BEq (β k)] -theorem checkBEq_eq_true_of_Equiv {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : m₁.1.Equiv m₂.1 → beq m₁ m₂ := by +theorem Equiv.beq [∀ k, ReflBEq (β k)] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : m₁.1.Equiv m₂.1 → beq m₁ m₂ := by simp_to_model using List.beqModel_eq_true_of_perm -theorem Equiv_of_checkBEq_eq_true {m₁ m₂ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : beq m₁ m₂ → m₁.1.Equiv m₂.1 := by +theorem Equiv_of_beq_eq_true [∀ k, LawfulBEq (β k)] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ → m₁.1.Equiv m₂.1 := by simp_to_model using List.perm_of_beqModel end BEq +namespace Const + +variable {β : Type v} +variable {m₁ m₂ : Raw₀ α (fun _ => β)} + +theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : m₁.1.Equiv m₂.1 → Const.beq m₁ m₂ := by + simp_to_model using List.Const.beqModel_eq_true_of_perm + +theorem Equiv_of_beq_eq_true [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ → m₁.1.Equiv m₂.1 := by + simp_to_model using List.Const.perm_of_beqModel + +end Const + section Union variable (m₁ m₂ : Raw₀ α β) diff --git a/src/Std/Data/DHashMap/Internal/WF.lean b/src/Std/Data/DHashMap/Internal/WF.lean index 97285e39d93a..e454382c3507 100644 --- a/src/Std/Data/DHashMap/Internal/WF.lean +++ b/src/Std/Data/DHashMap/Internal/WF.lean @@ -1519,4 +1519,23 @@ theorem toListModel_beq [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k) · exact h₂ · exact h₁ +theorem Const.toListModel_beq {β : Type v} [BEq α] [PartialEquivBEq α] [Hashable α] [LawfulHashable α] [BEq β] {m₁ m₂ : Raw₀ α (fun _ => β)} (h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) : + beq m₁ m₂ = Const.beqModel m₁.1.toList m₂.1.toList := by + rw [beq, Const.beqModel] + split + case isTrue h => + rw [Raw.size_eq_length, Raw.size_eq_length] at h + rw [Raw.toList_eq_toListModel, Raw.toList_eq_toListModel] + · simp only [ne_eq, h, not_false_eq_true, ↓reduceIte] + · exact h₂ + · exact h₁ + case isFalse h => + rw [Raw.size_eq_length, Raw.size_eq_length] at h + simp [Raw.toList_eq_toListModel, h, ← Raw.all_toList] + congr + · ext x + rw [get?_eq_getValue? h₂] + · exact h₂ + · exact h₁ + end Raw₀ diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index cd5aa9051caf..ed892366ed1d 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -1841,13 +1841,13 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] section BEq variable {m₁ m₂ : DHashMap α β} [LawfulBEq α] [∀ k, BEq (β k)] -theorem BEq_of_Equiv [∀ k, ReflBEq (β k)] (h : m₁ ~m m₂ ) : m₁ == m₂ := by +theorem Equiv.beq [∀ k, ReflBEq (β k)] (h : m₁ ~m m₂ ) : m₁ == m₂ := by simp [BEq.beq] - apply Raw₀.checkBEq_eq_true_of_Equiv m₁.2 m₂.2 h.1 + apply Raw₀.Equiv.beq m₁.2 m₂.2 h.1 -theorem Equiv.of_BEq [∀ k, LawfulBEq (β k)] (h : m₁ == m₂) : m₁ ~m m₂ := by +theorem Equiv_of_beq_eq_true [∀ k, LawfulBEq (β k)] (h : m₁ == m₂) : m₁ ~m m₂ := by constructor - have := @Raw₀.Equiv_of_checkBEq_eq_true α β _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 _ _ _ h + have := @Raw₀.Equiv_of_beq_eq_true α β _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h simp only at this exact this diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 7c89cfc6a00f..4a1bcf87a8ac 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -289,6 +289,10 @@ section variable {β : Type v} +/-- Internal implementation detail of the hash map -/ +def Const.beqModel [BEq α] [Hashable α] [BEq β] (l₁ l₂ : List ((_ : α) × β)) := + if l₁.length ≠ l₂.length then false else (l₁.all fun x => getValue? x.fst l₂ == some x.snd) + /-- This is a strange dependent version of `Option.map` in which the mapping function is allowed to "know" about the option that is being mapped. This happens to be useful in this file (see `getValueCast_eq_getEntry?`), but we do not want it to leak out of the file. -/ @@ -6719,6 +6723,28 @@ theorem beqModel_eq_true_of_perm [BEq α] [Hashable α] [LawfulBEq α] [LawfulB symm apply getValueCast?_of_perm hl₁ hyp +theorem Const.beqModel_eq_true_of_perm {β : Type v} [BEq α] [EquivBEq α] [Hashable α] [BEq β] [ReflBEq β] {l₁ l₂ : List ((_ : α) × β )} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → Const.beqModel l₁ l₂ := by + intro hyp + rw [beqModel] + split + case isTrue hlen => + rw [ne_eq] at hlen + apply Classical.byContradiction + intro _ + exact hlen <| List.Perm.length_eq hyp + case isFalse hlen => + simp only [List.all_eq_true] + intro ⟨k,v⟩ mem + have hv := @getValue_of_mem α β _ _ l₁ ⟨k,v⟩ mem + have hc := containsKey_of_mem mem + apply beq_of_eq + simp only at |- hc hv + rw [← hv, ← getValue?_eq_some_getValue] + · symm + apply getValue?_of_perm hl₁ hyp + · exact hl₁ + · exact hc + theorem perm_of_beqModel [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : beqModel l₁ l₂ → l₁.Perm l₂ := by rw [beqModel] @@ -6760,6 +6786,21 @@ theorem perm_of_beqModel [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k rw [Bool.not_eq_true] at hc₂ rw [getValueCast?_eq_none hc₁, getValueCast?_eq_none hc₂] +theorem beqModel_eq_beqModel_const {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] [BEq β] {l₁ l₂ : List ((_ : α) × β)} : beqModel l₁ l₂ = Const.beqModel l₁ l₂ := by + rw [beqModel, Const.beqModel] + congr + ext x + rw [getValue?_eq_getValueCast?] + +theorem Const.perm_of_beqModel {β : Type v} [BEq α] [Hashable α] [LawfulBEq α] [BEq β] [LawfulBEq β] {l₁ l₂ : List ((_ : α) × β)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : + beqModel l₁ l₂ → l₁.Perm l₂ := by + rw [← beqModel_eq_beqModel_const] + intro hyp + apply List.perm_of_beqModel + · exact hl₁ + · exact hl₂ + · exact hyp + namespace Const theorem getKey_getValue_mem [BEq α] [EquivBEq α] {β : Type v} {l : List ((_ : α) × β)} {k : α} {h} : From f4bce7466073e0c0753faefeb901d1e151ad9bcb Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 26 Nov 2025 13:03:55 +0000 Subject: [PATCH 10/72] push --- src/Std/Data/DHashMap/Internal/Defs.lean | 4 +++ src/Std/Data/DHashMap/Internal/RawLemmas.lean | 1 + src/Std/Data/DHashMap/Internal/WF.lean | 19 ++++++++++ src/Std/Data/Internal/List/Associative.lean | 35 +++++++++++++++++-- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/Std/Data/DHashMap/Internal/Defs.lean b/src/Std/Data/DHashMap/Internal/Defs.lean index 0bdf55378842..5dc9a6da1985 100644 --- a/src/Std/Data/DHashMap/Internal/Defs.lean +++ b/src/Std/Data/DHashMap/Internal/Defs.lean @@ -561,6 +561,10 @@ def getKey? [BEq α] [Hashable α] (m : Raw₀ α β) (a : α) : Option α := let ⟨i, h⟩ := mkIdx buckets.size h (hash a) buckets[i].getKey? a +/-- Internal implementation detail of the hash map -/ +def Const.beq_unit [BEq α] [Hashable α] (m₁ m₂ : Raw₀ α (fun _ => Unit)) : Bool := + if m₁.1.size ≠ m₂.1.size then false else m₁.1.all (fun k _ => m₂.contains k) + /-- Internal implementation detail of the hash map -/ def getKey [BEq α] [Hashable α] (m : Raw₀ α β) (a : α) (hma : m.contains a) : α := let ⟨⟨_, buckets⟩, h⟩ := m diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 46d4d4a1ae16..290af150f95e 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -164,6 +164,7 @@ private meta def queryMap : Std.DHashMap Name (fun _ => Name × Array (MacroM (T ⟨`getEntry!, (``getEntry!_eq_getEntry!, #[`(getEntry!_of_perm _)])⟩, ⟨`toList, (``Raw.toList_eq_toListModel, #[])⟩, ⟨`Const.beq, (``Raw₀.Const.toListModel_beq, #[])⟩, + ⟨`Const.beq_unit, (``Raw₀.Const.toListModel_beq_unit, #[])⟩, ⟨`beq, (``toListModel_beq, #[])⟩, ⟨`keys, (``Raw.keys_eq_keys_toListModel, #[`(perm_keys_congr_left)])⟩, ⟨`Const.toList, (``Raw.Const.toList_eq_toListModel_map, #[`(perm_map_congr_left)])⟩, diff --git a/src/Std/Data/DHashMap/Internal/WF.lean b/src/Std/Data/DHashMap/Internal/WF.lean index e454382c3507..b346c63eede7 100644 --- a/src/Std/Data/DHashMap/Internal/WF.lean +++ b/src/Std/Data/DHashMap/Internal/WF.lean @@ -1538,4 +1538,23 @@ theorem Const.toListModel_beq {β : Type v} [BEq α] [PartialEquivBEq α] [Hasha · exact h₂ · exact h₁ +theorem Const.toListModel_beq_unit [BEq α] [PartialEquivBEq α] [Hashable α] [LawfulHashable α] {m₁ m₂ : Raw₀ α (fun _ => Unit)} (h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) : + beq_unit m₁ m₂ = Const.beqModel_unit m₁.1.toList m₂.1.toList := by + rw [beq_unit, Const.beqModel_unit] + split + case isTrue h => + rw [Raw.size_eq_length, Raw.size_eq_length] at h + rw [Raw.toList_eq_toListModel, Raw.toList_eq_toListModel] + · simp only [ne_eq, h, not_false_eq_true, ↓reduceIte] + · exact h₂ + · exact h₁ + case isFalse h => + rw [Raw.size_eq_length, Raw.size_eq_length] at h + simp [Raw.toList_eq_toListModel, h, ← Raw.all_toList] + congr + · ext x + rw [contains_eq_containsKey h₂] + · exact h₂ + · exact h₁ + end Raw₀ diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 4a1bcf87a8ac..addbd60e8b5b 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -351,6 +351,10 @@ def containsKey [BEq α] (a : α) : List ((a : α) × β a) → Bool | [] => false | ⟨k, _⟩ :: l => k == a || containsKey a l +/-- Internal implementation detail of the hash map -/ +def Const.beqModel_unit [BEq α] [Hashable α] (l₁ l₂ : List ((_ : α) × Unit)) := + if l₁.length ≠ l₂.length then false else (l₁.all fun x => List.containsKey x.fst l₂) + @[simp] theorem containsKey_nil [BEq α] {a : α} : containsKey a ([] : List ((a : α) × β a)) = false := (rfl) @[simp] theorem containsKey_cons [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} : @@ -6703,7 +6707,7 @@ theorem isEmpty_filter_key_iff [BEq α] [EquivBEq α] {f : α → Bool} simp only [getKey, getKey?_eq_getEntry?, this] at h exact h -theorem beqModel_eq_true_of_perm [BEq α] [Hashable α] [LawfulBEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → beqModel l₁ l₂ := by +theorem beqModel_eq_true_of_perm [BEq α] [Hashable α] [LawfulBEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → beqModel l₁ l₂ := by intro hyp rw [beqModel] split @@ -6723,7 +6727,7 @@ theorem beqModel_eq_true_of_perm [BEq α] [Hashable α] [LawfulBEq α] [LawfulB symm apply getValueCast?_of_perm hl₁ hyp -theorem Const.beqModel_eq_true_of_perm {β : Type v} [BEq α] [EquivBEq α] [Hashable α] [BEq β] [ReflBEq β] {l₁ l₂ : List ((_ : α) × β )} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → Const.beqModel l₁ l₂ := by +theorem Const.beqModel_eq_true_of_perm {β : Type v} [BEq α] [EquivBEq α] [Hashable α] [BEq β] [ReflBEq β] {l₁ l₂ : List ((_ : α) × β )} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → Const.beqModel l₁ l₂ := by intro hyp rw [beqModel] split @@ -6745,6 +6749,22 @@ theorem Const.beqModel_eq_true_of_perm {β : Type v} [BEq α] [EquivBEq α] [Has · exact hl₁ · exact hc +theorem Const.beqModel_unit_eq_true_of_perm [BEq α] [EquivBEq α] [Hashable α] {l₁ l₂ : List ((_ : α) × Unit )} : l₁.Perm l₂ → Const.beqModel_unit l₁ l₂ := by + intro hyp + rw [beqModel_unit] + split + case isTrue hlen => + rw [ne_eq] at hlen + apply Classical.byContradiction + intro _ + exact hlen <| List.Perm.length_eq hyp + case isFalse hlen => + simp only [List.all_eq_true] + intro ⟨k, v⟩ mem + simp only + rw [containsKey_of_perm hyp.symm] + simp [containsKey_of_mem mem] + theorem perm_of_beqModel [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : beqModel l₁ l₂ → l₁.Perm l₂ := by rw [beqModel] @@ -6792,6 +6812,17 @@ theorem beqModel_eq_beqModel_const {β : Type v} [BEq α] [LawfulBEq α] [Hashab ext x rw [getValue?_eq_getValueCast?] +theorem beqModel_eq_beqModel_unit [BEq α] [LawfulBEq α] [Hashable α] {l₁ l₂ : List ((_ : α) × Unit)} : beqModel l₁ l₂ = Const.beqModel_unit l₁ l₂ := by + rw [beqModel, Const.beqModel_unit] + congr + ext x + rw [containsKey_eq_isSome_getValueCast?] + rw [← getValue?_eq_getValueCast?] + --apply (eq_iff_iff).2 + sorry + + + theorem Const.perm_of_beqModel {β : Type v} [BEq α] [Hashable α] [LawfulBEq α] [BEq β] [LawfulBEq β] {l₁ l₂ : List ((_ : α) × β)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : beqModel l₁ l₂ → l₁.Perm l₂ := by rw [← beqModel_eq_beqModel_const] From 4d6315903880b95d805ed3dba62bbcb5653eb6d3 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 26 Nov 2025 14:10:15 +0000 Subject: [PATCH 11/72] Add const lemma --- src/Std/Data/Internal/List/Associative.lean | 26 ++++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index addbd60e8b5b..52f03044be23 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -6816,12 +6816,17 @@ theorem beqModel_eq_beqModel_unit [BEq α] [LawfulBEq α] [Hashable α] {l₁ l rw [beqModel, Const.beqModel_unit] congr ext x - rw [containsKey_eq_isSome_getValueCast?] - rw [← getValue?_eq_getValueCast?] - --apply (eq_iff_iff).2 - sorry - - + rw [Bool.eq_iff_iff] + constructor + · intro hyp + rw [containsKey_eq_isSome_getValueCast?] + apply Option.isSome_of_eq_some + · apply eq_of_beq hyp + · intro hyp + apply beq_of_eq + rw [containsKey_eq_isSome_getValueCast?, Option.isSome_iff_exists ] at hyp + have ⟨_, hyp2⟩ := hyp + rw [hyp2] theorem Const.perm_of_beqModel {β : Type v} [BEq α] [Hashable α] [LawfulBEq α] [BEq β] [LawfulBEq β] {l₁ l₂ : List ((_ : α) × β)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : beqModel l₁ l₂ → l₁.Perm l₂ := by @@ -6832,6 +6837,15 @@ theorem Const.perm_of_beqModel {β : Type v} [BEq α] [Hashable α] [LawfulBEq · exact hl₂ · exact hyp +theorem Const.perm_of_beqModel_unit [BEq α] [Hashable α] [LawfulBEq α] {l₁ l₂ : List ((_ : α) × Unit)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : + beqModel_unit l₁ l₂ → l₁.Perm l₂ := by + rw [← beqModel_eq_beqModel_unit] + intro hyp + apply List.perm_of_beqModel + · exact hl₁ + · exact hl₂ + · exact hyp + namespace Const theorem getKey_getValue_mem [BEq α] [EquivBEq α] {β : Type v} {l : List ((_ : α) × β)} {k : α} {h} : From 09452de90d920d897ac72575c682cc2dc597021a Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 26 Nov 2025 16:48:47 +0000 Subject: [PATCH 12/72] Add perm lemmas --- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 23 ++++-- src/Std/Data/Internal/List/Associative.lean | 75 +++++++++++++++++++ 2 files changed, 90 insertions(+), 8 deletions(-) diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 290af150f95e..8db27aaf52cb 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -2596,25 +2596,32 @@ variable {m₁ m₂ : Raw₀ α β} [LawfulBEq α] [∀ k, BEq (β k)] theorem Equiv.beq [∀ k, ReflBEq (β k)] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : m₁.1.Equiv m₂.1 → beq m₁ m₂ := by simp_to_model using List.beqModel_eq_true_of_perm -theorem Equiv_of_beq_eq_true [∀ k, LawfulBEq (β k)] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ → m₁.1.Equiv m₂.1 := by +theorem Equiv_of_beq_eq_true [∀ k, LawfulBEq (β k)] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ = true → m₁.1.Equiv m₂.1 := by simp_to_model using List.perm_of_beqModel end BEq -namespace Const +section -variable {β : Type v} -variable {m₁ m₂ : Raw₀ α (fun _ => β)} +variable {β : Type v} {m₁ m₂ : Raw₀ α (fun _ => β)} -theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : m₁.1.Equiv m₂.1 → Const.beq m₁ m₂ := by +theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : m₁.1.Equiv m₂.1 → Const.beq m₁ m₂ := by simp_to_model using List.Const.beqModel_eq_true_of_perm -theorem Equiv_of_beq_eq_true [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ → m₁.1.Equiv m₂.1 := by +theorem Const.Equiv_of_beq_eq_true [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ = true → m₁.1.Equiv m₂.1 := by simp_to_model using List.Const.perm_of_beqModel +end -end Const +section + +variable {m₁ m₂ : Raw₀ α (fun _ => Unit)} + +theorem Const.Equiv.beq_unit [LawfulHashable α] [EquivBEq α] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : m₁.1.Equiv m₂.1 → Const.beq_unit m₁ m₂ := by + simp_to_model using List.Const.beqModel_unit_eq_true_of_perm -section Union +theorem Const.Equiv_of_beq_unit_eq_true [LawfulBEq α] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq_unit m₁ m₂ = true → m₁.1.Equiv m₂.1 := by + simp_to_model using List.Const.perm_of_beqModel_unit +end variable (m₁ m₂ : Raw₀ α β) diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 52f03044be23..3f2a7b1271cc 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -6806,6 +6806,81 @@ theorem perm_of_beqModel [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k rw [Bool.not_eq_true] at hc₂ rw [getValueCast?_eq_none hc₁, getValueCast?_eq_none hc₂] +theorem all_congr [BEq α] {l₁ l₂ : List ((a : α) × β a)} {f : (a : α) × β a → Bool} (hp : l₁.Perm l₂) : l₁.all f = l₂.all f := by + rw [Bool.eq_iff_iff, Bool.eq_iff_iff, List.all_eq_true, List.all_eq_true] + simp only [iff_true] + constructor + · intro hyp ⟨k,v⟩ mem + exact hyp ⟨k,v⟩ (@Perm.mem_iff _ ⟨k,v⟩ l₁ l₂ hp |>.2 mem) + · intro hyp ⟨k,v⟩ mem + exact hyp ⟨k,v⟩ (@Perm.mem_iff _ ⟨k,v⟩ l₂ l₁ hp.symm |>.2 mem) + +theorem beqModel_congr [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {l₁ l₂ l₃ l₄ : List ((a : α) × β a)} +(hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by + rw [beqModel] + split + case isTrue h => + rw [ne_eq] at h + rw [beqModel] + simp only [ne_eq, ite_not, Bool.if_false_right, Bool.false_eq, Bool.and_eq_false_imp, + decide_eq_true_eq] + intro hyp + rw [Perm.length_eq p₁, Perm.length_eq p₂] at h + contradiction + case isFalse h => + rw [beqModel] + rw [Perm.length_eq p₁, Perm.length_eq p₂] at h + simp only [h, ↓reduceIte] + have : fun (x : (a : α) × β a) => getValueCast? x.fst l₂ == some x.snd = fun x => getValueCast? x.fst l₄ == some x.snd := by + ext x + rw [getValueCast?_of_perm hl p₂] + rw [this] + apply all_congr p₁ + +theorem Const.beqModel_congr {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] [BEq β] {l₁ l₂ l₃ l₄ : List ((_ : α) × β)} +(hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by + rw [beqModel] + split + case isTrue h => + rw [ne_eq] at h + rw [beqModel] + simp only [ne_eq, ite_not, Bool.if_false_right, Bool.false_eq, Bool.and_eq_false_imp, + decide_eq_true_eq] + intro hyp + rw [Perm.length_eq p₁, Perm.length_eq p₂] at h + contradiction + case isFalse h => + rw [beqModel] + rw [Perm.length_eq p₁, Perm.length_eq p₂] at h + simp only [h, ↓reduceIte] + have : fun (x : (_ : α) × β) => getValue? x.fst l₂ == some x.snd = fun x => getValue? x.fst l₄ == some x.snd := by + ext x + rw [getValue?_of_perm hl p₂] + rw [this] + apply all_congr p₁ + +theorem Const.beqModel_unit_congr [BEq α] [LawfulBEq α] [Hashable α] {l₁ l₂ l₃ l₄ : List ((_ : α) × Unit)} +(p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel_unit l₁ l₂ = beqModel_unit l₃ l₄ := by + rw [beqModel_unit] + split + case isTrue h => + rw [ne_eq] at h + rw [beqModel_unit] + simp only [ne_eq, ite_not, Bool.if_false_right, Bool.false_eq, Bool.and_eq_false_imp, + decide_eq_true_eq] + intro hyp + rw [Perm.length_eq p₁, Perm.length_eq p₂] at h + contradiction + case isFalse h => + rw [beqModel_unit] + rw [Perm.length_eq p₁, Perm.length_eq p₂] at h + simp only [h, ↓reduceIte] + have : (fun x : ((_ : α) × Unit) => containsKey x.fst l₂) = (fun x => containsKey x.fst l₄) := by + ext x + rw [containsKey_of_perm p₂] + rw [this] + apply all_congr p₁ + theorem beqModel_eq_beqModel_const {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] [BEq β] {l₁ l₂ : List ((_ : α) × β)} : beqModel l₁ l₂ = Const.beqModel l₁ l₂ := by rw [beqModel, Const.beqModel] congr From fa88c40b9e685e22107927fe5a06313f48fa5ad0 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 26 Nov 2025 17:01:48 +0000 Subject: [PATCH 13/72] Congruence lemmas continued --- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 12 ++++++++++++ src/Std/Data/Internal/List/Associative.lean | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 8db27aaf52cb..7b46bc221309 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -2599,6 +2599,10 @@ theorem Equiv.beq [∀ k, ReflBEq (β k)] (h₁ : m₁.val.WF) (h₂ : m₂.val. theorem Equiv_of_beq_eq_true [∀ k, LawfulBEq (β k)] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ = true → m₁.1.Equiv m₂.1 := by simp_to_model using List.perm_of_beqModel +theorem Equiv.beq_congr {m₃ m₄ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) (h₃ : m₃.val.WF) (h₄ : m₄.val.WF) : + m₁.1.Equiv m₃.1 → m₂.1.Equiv m₄.1 → Raw₀.beq m₁ m₂ = Raw₀.beq m₃ m₄ := by + simp_to_model using List.beqModel_congr + end BEq section @@ -2610,6 +2614,10 @@ theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] theorem Const.Equiv_of_beq_eq_true [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ = true → m₁.1.Equiv m₂.1 := by simp_to_model using List.Const.perm_of_beqModel + +theorem Const.Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : Raw₀ α (fun _ => β)} [BEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) (h₃ : m₃.val.WF) (h₄ : m₄.val.WF) : + m₁.1.Equiv m₃.1 → m₂.1.Equiv m₄.1 → Const.beq m₁ m₂ = Const.beq m₃ m₄ := by + simp_to_model using List.Const.beqModel_congr end section @@ -2621,6 +2629,10 @@ theorem Const.Equiv.beq_unit [LawfulHashable α] [EquivBEq α] (h₁ : m₁.val. theorem Const.Equiv_of_beq_unit_eq_true [LawfulBEq α] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq_unit m₁ m₂ = true → m₁.1.Equiv m₂.1 := by simp_to_model using List.Const.perm_of_beqModel_unit + +theorem Const.Equiv.beq_unit_congr [LawfulBEq α] {m₃ m₄ : Raw₀ α (fun _ => Unit)} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) (h₃ : m₃.val.WF) (h₄ : m₄.val.WF) : + m₁.1.Equiv m₃.1 → m₂.1.Equiv m₄.1 → Const.beq_unit m₁ m₂ = Const.beq_unit m₃ m₄ := by + simp_to_model using List.Const.beqModel_unit_congr end variable (m₁ m₂ : Raw₀ α β) diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 3f2a7b1271cc..3031f86a876c 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -6815,7 +6815,7 @@ theorem all_congr [BEq α] {l₁ l₂ : List ((a : α) × β a)} {f : (a : α) · intro hyp ⟨k,v⟩ mem exact hyp ⟨k,v⟩ (@Perm.mem_iff _ ⟨k,v⟩ l₂ l₁ hp.symm |>.2 mem) -theorem beqModel_congr [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {l₁ l₂ l₃ l₄ : List ((a : α) × β a)} +theorem beqModel_congr [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] {l₁ l₂ l₃ l₄ : List ((a : α) × β a)} (hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by rw [beqModel] split From fcad743e7ee4d7d0c9f2d05227b032cb7c6b563a Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 26 Nov 2025 17:22:22 +0000 Subject: [PATCH 14/72] fix scoping issue --- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 7b46bc221309..dd7fcbe5f82a 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -2635,6 +2635,7 @@ theorem Const.Equiv.beq_unit_congr [LawfulBEq α] {m₃ m₄ : Raw₀ α (fun _ simp_to_model using List.Const.beqModel_unit_congr end +section Union variable (m₁ m₂ : Raw₀ α β) variable {m₁ m₂} From bd7dca5cc2c414027685c1419d5270da6d687b90 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 26 Nov 2025 17:57:40 +0000 Subject: [PATCH 15/72] Remove unit variant and add the raw variant --- src/Std/Data/DHashMap/Basic.lean | 11 ++- src/Std/Data/DHashMap/Internal/Defs.lean | 4 -- src/Std/Data/DHashMap/Internal/Raw.lean | 8 +++ src/Std/Data/DHashMap/Internal/RawLemmas.lean | 16 ----- src/Std/Data/DHashMap/Internal/WF.lean | 19 ------ src/Std/Data/DHashMap/Lemmas.lean | 2 +- src/Std/Data/DHashMap/Raw.lean | 31 +++++++++ src/Std/Data/DHashMap/RawLemmas.lean | 2 +- src/Std/Data/Internal/List/Associative.lean | 67 ------------------- 9 files changed, 50 insertions(+), 110 deletions(-) diff --git a/src/Std/Data/DHashMap/Basic.lean b/src/Std/Data/DHashMap/Basic.lean index 8845ffa38bd9..7e8cf699568a 100644 --- a/src/Std/Data/DHashMap/Basic.lean +++ b/src/Std/Data/DHashMap/Basic.lean @@ -349,8 +349,15 @@ This function always iterates through the smaller map, so the expected runtime i instance [BEq α] [Hashable α] : Union (DHashMap α β) := ⟨union⟩ instance [BEq α] [Hashable α] : Inter (DHashMap α β) := ⟨inter⟩ -instance [LawfulBEq α] [∀ k, BEq (β k)] : BEq (DHashMap α β) where - beq a b := Raw₀.beq ⟨a.1, a.2.size_buckets_pos⟩ ⟨b.1, b.2.size_buckets_pos⟩ +/-- Internal implementation detail of the hash map. -/ +def beq [LawfulBEq α] [∀ k, BEq (β k)] (a b : DHashMap α β) : Bool := + Raw₀.beq ⟨a.1, a.2.size_buckets_pos⟩ ⟨b.1, b.2.size_buckets_pos⟩ + +instance [LawfulBEq α] [∀ k, BEq (β k)] : BEq (DHashMap α β) := ⟨beq⟩ + +/-- Internal implementation detail of the hash map. -/ +def Const.beq {β : Type v} [BEq α] [BEq β] (m₁ m₂ : DHashMap α (fun _ => β)) : Bool := + Raw₀.Const.beq ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ section Unverified diff --git a/src/Std/Data/DHashMap/Internal/Defs.lean b/src/Std/Data/DHashMap/Internal/Defs.lean index 5dc9a6da1985..0bdf55378842 100644 --- a/src/Std/Data/DHashMap/Internal/Defs.lean +++ b/src/Std/Data/DHashMap/Internal/Defs.lean @@ -561,10 +561,6 @@ def getKey? [BEq α] [Hashable α] (m : Raw₀ α β) (a : α) : Option α := let ⟨i, h⟩ := mkIdx buckets.size h (hash a) buckets[i].getKey? a -/-- Internal implementation detail of the hash map -/ -def Const.beq_unit [BEq α] [Hashable α] (m₁ m₂ : Raw₀ α (fun _ => Unit)) : Bool := - if m₁.1.size ≠ m₂.1.size then false else m₁.1.all (fun k _ => m₂.contains k) - /-- Internal implementation detail of the hash map -/ def getKey [BEq α] [Hashable α] (m : Raw₀ α β) (a : α) (hma : m.contains a) : α := let ⟨⟨_, buckets⟩, h⟩ := m diff --git a/src/Std/Data/DHashMap/Internal/Raw.lean b/src/Std/Data/DHashMap/Internal/Raw.lean index b421e0f6caf2..da17faa139e8 100644 --- a/src/Std/Data/DHashMap/Internal/Raw.lean +++ b/src/Std/Data/DHashMap/Internal/Raw.lean @@ -149,6 +149,14 @@ theorem inter_eq [BEq α] [Hashable α] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) m₁.inter m₂ = Raw₀.inter ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ := by simp [Raw.inter, h₁.size_buckets_pos, h₂.size_buckets_pos] +theorem beq_eq [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : + m₁.beq m₂ = Raw₀.beq ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ := by + simp [Raw.beq, h₁.size_buckets_pos, h₂.size_buckets_pos] + +theorem Const.beq_eq {β : Type v} [BEq α] [Hashable α] [BEq β] {m₁ m₂ : Raw α (fun _ => β)} (h₁ : m₁.WF) (h₂ : m₂.WF) : + Raw.Const.beq m₁ m₂ = Raw₀.Const.beq ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ := by + simp [Raw.Const.beq, h₁.size_buckets_pos, h₂.size_buckets_pos] + section variable {β : Type v} diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index dd7fcbe5f82a..fdac05d809be 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -164,7 +164,6 @@ private meta def queryMap : Std.DHashMap Name (fun _ => Name × Array (MacroM (T ⟨`getEntry!, (``getEntry!_eq_getEntry!, #[`(getEntry!_of_perm _)])⟩, ⟨`toList, (``Raw.toList_eq_toListModel, #[])⟩, ⟨`Const.beq, (``Raw₀.Const.toListModel_beq, #[])⟩, - ⟨`Const.beq_unit, (``Raw₀.Const.toListModel_beq_unit, #[])⟩, ⟨`beq, (``toListModel_beq, #[])⟩, ⟨`keys, (``Raw.keys_eq_keys_toListModel, #[`(perm_keys_congr_left)])⟩, ⟨`Const.toList, (``Raw.Const.toList_eq_toListModel_map, #[`(perm_map_congr_left)])⟩, @@ -2620,21 +2619,6 @@ theorem Const.Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : Raw₀ α (fun _ => β simp_to_model using List.Const.beqModel_congr end -section - -variable {m₁ m₂ : Raw₀ α (fun _ => Unit)} - -theorem Const.Equiv.beq_unit [LawfulHashable α] [EquivBEq α] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : m₁.1.Equiv m₂.1 → Const.beq_unit m₁ m₂ := by - simp_to_model using List.Const.beqModel_unit_eq_true_of_perm - -theorem Const.Equiv_of_beq_unit_eq_true [LawfulBEq α] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq_unit m₁ m₂ = true → m₁.1.Equiv m₂.1 := by - simp_to_model using List.Const.perm_of_beqModel_unit - -theorem Const.Equiv.beq_unit_congr [LawfulBEq α] {m₃ m₄ : Raw₀ α (fun _ => Unit)} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) (h₃ : m₃.val.WF) (h₄ : m₄.val.WF) : - m₁.1.Equiv m₃.1 → m₂.1.Equiv m₄.1 → Const.beq_unit m₁ m₂ = Const.beq_unit m₃ m₄ := by - simp_to_model using List.Const.beqModel_unit_congr -end - section Union variable (m₁ m₂ : Raw₀ α β) diff --git a/src/Std/Data/DHashMap/Internal/WF.lean b/src/Std/Data/DHashMap/Internal/WF.lean index b346c63eede7..e454382c3507 100644 --- a/src/Std/Data/DHashMap/Internal/WF.lean +++ b/src/Std/Data/DHashMap/Internal/WF.lean @@ -1538,23 +1538,4 @@ theorem Const.toListModel_beq {β : Type v} [BEq α] [PartialEquivBEq α] [Hasha · exact h₂ · exact h₁ -theorem Const.toListModel_beq_unit [BEq α] [PartialEquivBEq α] [Hashable α] [LawfulHashable α] {m₁ m₂ : Raw₀ α (fun _ => Unit)} (h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) : - beq_unit m₁ m₂ = Const.beqModel_unit m₁.1.toList m₂.1.toList := by - rw [beq_unit, Const.beqModel_unit] - split - case isTrue h => - rw [Raw.size_eq_length, Raw.size_eq_length] at h - rw [Raw.toList_eq_toListModel, Raw.toList_eq_toListModel] - · simp only [ne_eq, h, not_false_eq_true, ↓reduceIte] - · exact h₂ - · exact h₁ - case isFalse h => - rw [Raw.size_eq_length, Raw.size_eq_length] at h - simp [Raw.toList_eq_toListModel, h, ← Raw.all_toList] - congr - · ext x - rw [contains_eq_containsKey h₂] - · exact h₂ - · exact h₁ - end Raw₀ diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index ed892366ed1d..cf527120f078 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -1841,7 +1841,7 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] section BEq variable {m₁ m₂ : DHashMap α β} [LawfulBEq α] [∀ k, BEq (β k)] -theorem Equiv.beq [∀ k, ReflBEq (β k)] (h : m₁ ~m m₂ ) : m₁ == m₂ := by +theorem Equiv.beq [∀ k, ReflBEq (β k)] (h : m₁ ~m m₂) : m₁ == m₂ := by simp [BEq.beq] apply Raw₀.Equiv.beq m₁.2 m₂.2 h.1 diff --git a/src/Std/Data/DHashMap/Raw.lean b/src/Std/Data/DHashMap/Raw.lean index bd08a15ce10f..871dc4282286 100644 --- a/src/Std/Data/DHashMap/Raw.lean +++ b/src/Std/Data/DHashMap/Raw.lean @@ -511,6 +511,37 @@ This function always merges the smaller map into the larger map, so the expected instance [BEq α] [Hashable α] : Inter (Raw α β) := ⟨inter⟩ +/-- Internal implementation detail of the hash map. -/ +def beq [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] (m₁ m₂ : Raw α β) : Bool := + if h₁ : 0 < m₁.buckets.size then + if h₂ : 0 < m₂.buckets.size then + Raw₀.beq ⟨m₁, h₁⟩ ⟨m₂, h₂⟩ + else + false + else + false + +instance [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] : BEq (Raw α β) := ⟨beq⟩ + +/-- Internal implementation detail of the hash map. -/ +def Const.beq {β : Type v} [BEq α] [Hashable α] [BEq β] (m₁ m₂ : Raw α (fun _ => β)) : Bool := + if h₁ : 0 < m₁.buckets.size then + if h₂ : 0 < m₂.buckets.size then + Raw₀.Const.beq ⟨m₁, h₁⟩ ⟨m₂, h₂⟩ + else + false + else + false + +/-- Internal implementation detail of the hash map. -/ +def Const.beq_const [BEq α] [Hashable α] (m₁ m₂ : Raw α (fun _ => Unit)) : Bool := + if h₁ : 0 < m₁.buckets.size then + if h₂ : 0 < m₂.buckets.size then + Raw₀.Const.beq ⟨m₁, h₁⟩ ⟨m₂, h₂⟩ + else + false + else + false section Unverified diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index ab94456b5d58..50c04e7443cc 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -47,7 +47,7 @@ private meta def baseNames : Array Name := ``getKey?_eq, ``getKey_eq, ``getKey!_eq, ``getKeyD_eq, ``insertMany_eq, ``Const.insertMany_eq, ``Const.insertManyIfNewUnit_eq, ``ofList_eq, ``Const.ofList_eq, ``Const.unitOfList_eq, - ``alter_eq, ``Const.alter_eq, ``modify_eq, ``Const.modify_eq, ``union_eq, ``inter_eq] + ``alter_eq, ``Const.alter_eq, ``modify_eq, ``Const.modify_eq, ``union_eq, ``inter_eq, ``beq_eq, ``Const.beq_eq] /-- Internal implementation detail of the hash map -/ scoped syntax "simp_to_raw" ("using" term)? : tactic diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 3031f86a876c..1648499dd313 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -351,10 +351,6 @@ def containsKey [BEq α] (a : α) : List ((a : α) × β a) → Bool | [] => false | ⟨k, _⟩ :: l => k == a || containsKey a l -/-- Internal implementation detail of the hash map -/ -def Const.beqModel_unit [BEq α] [Hashable α] (l₁ l₂ : List ((_ : α) × Unit)) := - if l₁.length ≠ l₂.length then false else (l₁.all fun x => List.containsKey x.fst l₂) - @[simp] theorem containsKey_nil [BEq α] {a : α} : containsKey a ([] : List ((a : α) × β a)) = false := (rfl) @[simp] theorem containsKey_cons [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} : @@ -6749,22 +6745,6 @@ theorem Const.beqModel_eq_true_of_perm {β : Type v} [BEq α] [EquivBEq α] [Has · exact hl₁ · exact hc -theorem Const.beqModel_unit_eq_true_of_perm [BEq α] [EquivBEq α] [Hashable α] {l₁ l₂ : List ((_ : α) × Unit )} : l₁.Perm l₂ → Const.beqModel_unit l₁ l₂ := by - intro hyp - rw [beqModel_unit] - split - case isTrue hlen => - rw [ne_eq] at hlen - apply Classical.byContradiction - intro _ - exact hlen <| List.Perm.length_eq hyp - case isFalse hlen => - simp only [List.all_eq_true] - intro ⟨k, v⟩ mem - simp only - rw [containsKey_of_perm hyp.symm] - simp [containsKey_of_mem mem] - theorem perm_of_beqModel [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : beqModel l₁ l₂ → l₁.Perm l₂ := by rw [beqModel] @@ -6859,50 +6839,12 @@ theorem Const.beqModel_congr {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] rw [this] apply all_congr p₁ -theorem Const.beqModel_unit_congr [BEq α] [LawfulBEq α] [Hashable α] {l₁ l₂ l₃ l₄ : List ((_ : α) × Unit)} -(p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel_unit l₁ l₂ = beqModel_unit l₃ l₄ := by - rw [beqModel_unit] - split - case isTrue h => - rw [ne_eq] at h - rw [beqModel_unit] - simp only [ne_eq, ite_not, Bool.if_false_right, Bool.false_eq, Bool.and_eq_false_imp, - decide_eq_true_eq] - intro hyp - rw [Perm.length_eq p₁, Perm.length_eq p₂] at h - contradiction - case isFalse h => - rw [beqModel_unit] - rw [Perm.length_eq p₁, Perm.length_eq p₂] at h - simp only [h, ↓reduceIte] - have : (fun x : ((_ : α) × Unit) => containsKey x.fst l₂) = (fun x => containsKey x.fst l₄) := by - ext x - rw [containsKey_of_perm p₂] - rw [this] - apply all_congr p₁ - theorem beqModel_eq_beqModel_const {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] [BEq β] {l₁ l₂ : List ((_ : α) × β)} : beqModel l₁ l₂ = Const.beqModel l₁ l₂ := by rw [beqModel, Const.beqModel] congr ext x rw [getValue?_eq_getValueCast?] -theorem beqModel_eq_beqModel_unit [BEq α] [LawfulBEq α] [Hashable α] {l₁ l₂ : List ((_ : α) × Unit)} : beqModel l₁ l₂ = Const.beqModel_unit l₁ l₂ := by - rw [beqModel, Const.beqModel_unit] - congr - ext x - rw [Bool.eq_iff_iff] - constructor - · intro hyp - rw [containsKey_eq_isSome_getValueCast?] - apply Option.isSome_of_eq_some - · apply eq_of_beq hyp - · intro hyp - apply beq_of_eq - rw [containsKey_eq_isSome_getValueCast?, Option.isSome_iff_exists ] at hyp - have ⟨_, hyp2⟩ := hyp - rw [hyp2] - theorem Const.perm_of_beqModel {β : Type v} [BEq α] [Hashable α] [LawfulBEq α] [BEq β] [LawfulBEq β] {l₁ l₂ : List ((_ : α) × β)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : beqModel l₁ l₂ → l₁.Perm l₂ := by rw [← beqModel_eq_beqModel_const] @@ -6912,15 +6854,6 @@ theorem Const.perm_of_beqModel {β : Type v} [BEq α] [Hashable α] [LawfulBEq · exact hl₂ · exact hyp -theorem Const.perm_of_beqModel_unit [BEq α] [Hashable α] [LawfulBEq α] {l₁ l₂ : List ((_ : α) × Unit)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : - beqModel_unit l₁ l₂ → l₁.Perm l₂ := by - rw [← beqModel_eq_beqModel_unit] - intro hyp - apply List.perm_of_beqModel - · exact hl₁ - · exact hl₂ - · exact hyp - namespace Const theorem getKey_getValue_mem [BEq α] [EquivBEq α] {β : Type v} {l : List ((_ : α) × β)} {k : α} {h} : From f37ad5f5db26f25fdd694f4d48b9f0c445adf9de Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 26 Nov 2025 18:10:59 +0000 Subject: [PATCH 16/72] Add lemmas to DHashMap --- src/Std/Data/DHashMap/Lemmas.lean | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index cf527120f078..1d56a14b1667 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -1851,8 +1851,28 @@ theorem Equiv_of_beq_eq_true [∀ k, LawfulBEq (β k)] (h : m₁ == m₂) : m₁ simp only at this exact this +theorem Equiv.beq_congr {m₃ m₄ : DHashMap α β} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := by + intro h1 h2 + exact @Raw₀.Equiv.beq_congr α β _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ ⟨m₃.1, m₃.2.size_buckets_pos⟩ ⟨m₄.1, m₄.2.size_buckets_pos⟩ m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 end BEq +section +variable {β : Type v} {m₁ m₂ : DHashMap α (fun _ => β)} [BEq β] + +theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [ReflBEq β] (h : m₁ ~m m₂) : DHashMap.Const.beq m₁ m₂ := by + apply Raw₀.Const.Equiv.beq m₁.2 m₂.2 h.1 + +theorem Const.Equiv_of_beq_eq_true [LawfulBEq α] [LawfulBEq β] (h : Const.beq m₁ m₂) : m₁ ~m m₂ := by + constructor + have := @Raw₀.Const.Equiv_of_beq_eq_true α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h + simp only at this + exact this + +theorem Const.Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : DHashMap α (fun _ => β)} : m₁ ~m m₃ → m₂ ~m m₄ → Const.beq m₁ m₂ = Const.beq m₃ m₄ := by + intro h1 h2 + exact @Raw₀.Const.Equiv.beq_congr α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ ⟨m₃.1, m₃.2.size_buckets_pos⟩ ⟨m₄.1, m₄.2.size_buckets_pos⟩ _ m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 +end + section Union variable (m₁ m₂ : DHashMap α β) From 9ce4b8c14a1ab8118f28701381f48521a20532e4 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 26 Nov 2025 19:21:07 +0000 Subject: [PATCH 17/72] Add Raw DHashMapLemmas --- src/Std/Data/DHashMap/RawLemmas.lean | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index 50c04e7443cc..2c95dc468355 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -3298,6 +3298,44 @@ variable [BEq α] [Hashable α] open Internal.Raw Internal.Raw₀ +section BEq +variable {m₁ m₂ : Raw α β} [LawfulBEq α] [∀ k, BEq (β k)] + +theorem Equiv.beq [∀ k, ReflBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := by + simp_to_raw + intro h + exact Raw₀.Equiv.beq h₁ h₂ h + +theorem Equiv_of_beq_eq_true [∀ k, LawfulBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) : beq m₁ m₂ = true → m₁ ~m m₂ := by + simp_to_raw using Raw₀.Equiv_of_beq_eq_true + +theorem Equiv.beq_congr {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : + m₁ ~m m₃ → m₂ ~m m₄ → Raw.beq m₁ m₂ = Raw.beq m₃ m₄ := by + simp_to_raw + intro w1 w2 + exact Raw₀.Equiv.beq_congr h₁ h₂ h₃ h₄ w1 w2 + +end BEq + +section +variable {β : Type v} {m₁ m₂ : Raw α (fun _ => β)} + +theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := by + simp_to_raw + intro h + exact Raw₀.Const.Equiv.beq h₁ h₂ h + +theorem Const.Equiv_of_beq_eq_true [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : beq m₁ m₂ = true → m₁ ~m m₂ := by + simp_to_raw using Raw₀.Const.Equiv_of_beq_eq_true + +theorem Const.Equiv.beq_congr [LawfulBEq α] [BEq β] {m₃ m₄ : Raw α (fun _ => β)} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : + m₁ ~m m₃ → m₂ ~m m₄ → Raw.Const.beq m₁ m₂ = Raw.Const.beq m₃ m₄ := by + simp_to_raw + intro w1 w2 + exact Raw₀.Const.Equiv.beq_congr h₁ h₂ h₃ h₄ w1 w2 + +end + @[simp, grind =] theorem ofList_nil : ofList ([] : List ((a : α) × (β a))) = ∅ := by From 3afdb457ad236e6537d47392ed8b100d2204de17 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 26 Nov 2025 21:59:01 +0000 Subject: [PATCH 18/72] Done with lemmas --- src/Std/Data/HashMap/Basic.lean | 6 ++++++ src/Std/Data/HashMap/Lemmas.lean | 14 ++++++++++++++ src/Std/Data/HashMap/Raw.lean | 6 ++++++ src/Std/Data/HashMap/RawLemmas.lean | 15 +++++++++++++++ src/Std/Data/HashSet/Basic.lean | 6 ++++++ src/Std/Data/HashSet/Lemmas.lean | 14 ++++++++++++++ src/Std/Data/HashSet/Raw.lean | 6 ++++++ src/Std/Data/HashSet/RawLemmas.lean | 15 +++++++++++++++ 8 files changed, 82 insertions(+) diff --git a/src/Std/Data/HashMap/Basic.lean b/src/Std/Data/HashMap/Basic.lean index 941caf239a85..2c019a8adeb0 100644 --- a/src/Std/Data/HashMap/Basic.lean +++ b/src/Std/Data/HashMap/Basic.lean @@ -274,6 +274,12 @@ instance [BEq α] [Hashable α] : Union (HashMap α β) := ⟨union⟩ instance [BEq α] [Hashable α] : Inter (HashMap α β) := ⟨inter⟩ +/-- Internal implementation detail of the hash map. -/ +def beq {β : Type v} [BEq α] [BEq β] (m₁ m₂ : HashMap α β) : Bool := + DHashMap.Const.beq m₁.inner m₂.inner + +instance [BEq α] [BEq β] : BEq (HashMap α β) := ⟨beq⟩ + section Unverified /-! We currently do not provide lemmas for the functions below. -/ diff --git a/src/Std/Data/HashMap/Lemmas.lean b/src/Std/Data/HashMap/Lemmas.lean index d81fcff5f7ea..5c78fc271d08 100644 --- a/src/Std/Data/HashMap/Lemmas.lean +++ b/src/Std/Data/HashMap/Lemmas.lean @@ -1346,6 +1346,20 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] {l : ρ} : (insertMany m l).isEmpty → m.isEmpty := DHashMap.Const.isEmpty_of_isEmpty_insertMany +section +variable {β : Type v} {m₁ m₂ : HashMap α β} [BEq β] + +theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [ReflBEq β] (h : m₁ ~m m₂) : m₁ == m₂ := + DHashMap.Const.Equiv.beq h.1 + +theorem Equiv_of_beq_eq_true [LawfulBEq α] [LawfulBEq β] (h : m₁ == m₂) : m₁ ~m m₂ := + ⟨DHashMap.Const.Equiv_of_beq_eq_true h⟩ + +theorem Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : HashMap α β} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun h1 h2 => + DHashMap.Const.Equiv.beq_congr h1.1 h2.1 + +end + section Union variable {β : Type v} diff --git a/src/Std/Data/HashMap/Raw.lean b/src/Std/Data/HashMap/Raw.lean index 2c4ca703d606..65716ade1926 100644 --- a/src/Std/Data/HashMap/Raw.lean +++ b/src/Std/Data/HashMap/Raw.lean @@ -241,6 +241,12 @@ instance [BEq α] [Hashable α] : Union (Raw α β) := ⟨union⟩ instance [BEq α] [Hashable α] : Inter (Raw α β) := ⟨inter⟩ +/-- Internal implementation detail of the hash map. -/ +def beq {β : Type v} [BEq α] [Hashable α] [BEq β] (m₁ m₂ : Raw α β) : Bool := + DHashMap.Raw.Const.beq m₁.inner m₂.inner + +instance [BEq α] [Hashable α] [BEq β] : BEq (Raw α β) := ⟨beq⟩ + section Unverified @[inline, inherit_doc DHashMap.Raw.filterMap] def filterMap {γ : Type w} (f : α → β → Option γ) diff --git a/src/Std/Data/HashMap/RawLemmas.lean b/src/Std/Data/HashMap/RawLemmas.lean index aff224922a3d..b393ea749256 100644 --- a/src/Std/Data/HashMap/RawLemmas.lean +++ b/src/Std/Data/HashMap/RawLemmas.lean @@ -1308,6 +1308,21 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] (h : m.W {l : ρ} : (insertMany m l).isEmpty → m.isEmpty := DHashMap.Raw.Const.isEmpty_of_isEmpty_insertMany h.out +section +variable {β : Type v} {m₁ m₂ : Raw α β} + +theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := fun hyp => + @DHashMap.Raw.Const.Equiv.beq _ _ _ _ m₁.1 m₂.1 _ _ _ _ h₁.1 h₂.1 hyp.1 + +theorem Equiv_of_beq_eq_true [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := fun hyp => + ⟨@DHashMap.Raw.Const.Equiv_of_beq_eq_true _ _ _ _ m₁.1 m₂.1 _ _ _ h₁.1 h₂.1 hyp⟩ + +theorem Equiv.beq_congr [LawfulBEq α] [BEq β] {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : + m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun hyp1 hyp2 => + @DHashMap.Raw.Const.Equiv.beq_congr _ _ _ _ m₁.1 m₂.1 _ _ m₃.1 m₄.1 h₁.1 h₂.1 h₃.1 h₄.1 hyp1.1 hyp2.1 + +end + section Union variable {β : Type v} diff --git a/src/Std/Data/HashSet/Basic.lean b/src/Std/Data/HashSet/Basic.lean index f59584ac4cb4..1b4ae29c0ba5 100644 --- a/src/Std/Data/HashSet/Basic.lean +++ b/src/Std/Data/HashSet/Basic.lean @@ -259,6 +259,12 @@ This function always iterates through the smaller set, so the expected runtime i instance [BEq α] [Hashable α] : Inter (HashSet α) := ⟨inter⟩ +/-- Internal implementation detail of the hash map. -/ +def beq [BEq α] (m₁ m₂ : HashSet α) : Bool := + HashMap.beq m₁.inner m₂.inner + +instance [BEq α] : BEq (HashSet α) := ⟨beq⟩ + section Unverified /-! We currently do not provide lemmas for the functions below. -/ diff --git a/src/Std/Data/HashSet/Lemmas.lean b/src/Std/Data/HashSet/Lemmas.lean index 3477057f09bf..fb9abe82edb3 100644 --- a/src/Std/Data/HashSet/Lemmas.lean +++ b/src/Std/Data/HashSet/Lemmas.lean @@ -782,6 +782,20 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] end +section +variable {m₁ m₂ : HashSet α} + +theorem Equiv.beq [LawfulHashable α] [EquivBEq α] (h : m₁ ~m m₂) : m₁ == m₂ := + HashMap.Equiv.beq h.1 + +theorem Equiv_of_beq_eq_true [LawfulBEq α] (h : m₁ == m₂) : m₁ ~m m₂ := + ⟨HashMap.Equiv_of_beq_eq_true h⟩ + +theorem Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : HashSet α} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun h1 h2 => + HashMap.Equiv.beq_congr h1.1 h2.1 + +end + section Union variable (m₁ m₂ : HashSet α) diff --git a/src/Std/Data/HashSet/Raw.lean b/src/Std/Data/HashSet/Raw.lean index 49824e3e7fb4..cb1312edc638 100644 --- a/src/Std/Data/HashSet/Raw.lean +++ b/src/Std/Data/HashSet/Raw.lean @@ -243,6 +243,12 @@ This function always merges the smaller set into the larger set, so the expected instance [BEq α] [Hashable α] : Inter (Raw α) := ⟨inter⟩ +/-- Internal implementation detail of the hash map. -/ +def beq [BEq α] [Hashable α] (m₁ m₂ : Raw α) : Bool := + HashMap.Raw.beq m₁.inner m₂.inner + +instance [BEq α] [Hashable α] : BEq (Raw α) := ⟨beq⟩ + section Unverified /-! We currently do not provide lemmas for the functions below. -/ diff --git a/src/Std/Data/HashSet/RawLemmas.lean b/src/Std/Data/HashSet/RawLemmas.lean index 3015d058b95c..b6a4ddd134e8 100644 --- a/src/Std/Data/HashSet/RawLemmas.lean +++ b/src/Std/Data/HashSet/RawLemmas.lean @@ -814,6 +814,21 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] (h : m.W {l : ρ} : (insertMany m l).isEmpty → m.isEmpty := HashMap.Raw.isEmpty_of_isEmpty_insertManyIfNewUnit h.out +section +variable {m₁ m₂ : Raw α} + +theorem Equiv.beq [LawfulHashable α] [EquivBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := fun hyp => + @HashMap.Raw.Equiv.beq _ _ _ _ m₁.1 m₂.1 _ _ _ _ h₁.1 h₂.1 hyp.1 + +theorem Equiv_of_beq_eq_true [LawfulBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := fun hyp => + ⟨@HashMap.Raw.Equiv_of_beq_eq_true _ _ _ _ m₁.1 m₂.1 _ _ _ h₁.1 h₂.1 hyp⟩ + +theorem Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : + m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun hyp1 hyp2 => + @HashMap.Raw.Equiv.beq_congr _ _ _ _ m₁.1 m₂.1 _ _ m₃.1 m₄.1 h₁.1 h₂.1 h₃.1 h₄.1 hyp1.1 hyp2.1 + +end + section Union variable (m₁ m₂ : Raw α) From d985064f3c6623ba05ea4d2e66f1c2c95c1981c3 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 26 Nov 2025 22:48:50 +0000 Subject: [PATCH 19/72] ExtHashMap done --- src/Std/Data/ExtDHashMap/Basic.lean | 63 ++++++++++++++++++++++++++++- src/Std/Data/ExtHashMap/Basic.lean | 19 +++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index 706beda46071..61bf6a3a3d0b 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -363,7 +363,68 @@ def union [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtDHashMap α β) : Ex . exact equiv₁ . exact equiv₂) m₁ m₂ -instance [EquivBEq α] [LawfulHashable α] : Union (ExtDHashMap α β) := ⟨union⟩ +@[inline, inherit_doc DHashMap.beq] +def beq [LawfulBEq α] [∀ k, BEq (β k)] (m₁ m₂ : ExtDHashMap α β) : Bool := lift₂ (fun x y : DHashMap α β => x.beq y) + (fun _ _ _ _ => DHashMap.Equiv.beq_congr) m₁ m₂ + +instance [LawfulBEq α] [∀ k, BEq (β k)] : BEq (ExtDHashMap α β) := ⟨beq⟩ + +instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : ReflBEq (ExtDHashMap α β) where + rfl := by + intro a + induction a + case mk a => + simp only [BEq.beq, beq] + apply DHashMap.Equiv.beq + apply DHashMap.Equiv.refl + +instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : LawfulBEq (ExtDHashMap α β) where + eq_of_beq := by + intro a b hyp + induction a + case mk a₀ => + induction b + case mk b₀ => + apply sound <| DHashMap.Equiv_of_beq_eq_true hyp + +namespace Const + +variable {β : Type v} +@[inline, inherit_doc DHashMap.beq] +def beq [LawfulBEq α] [BEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) : Bool := lift₂ (fun x y : DHashMap α fun _ => β => DHashMap.Const.beq x y) + (fun _ _ _ _ => DHashMap.Const.Equiv.beq_congr) m₁ m₂ + +theorem beq_of_eq [LawfulBEq α] [BEq β] [ReflBEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) (h : m₁ = m₂) : Const.beq m₁ m₂ := by + induction m₁ + case mk a => + induction m₂ + case mk b => + exact DHashMap.Const.Equiv.beq <| exact h + +theorem eq_of_beq_eq_true [LawfulBEq α] [BEq β] [LawfulBEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) (h : Const.beq m₁ m₂) : m₁ = m₂ := by + induction m₁ + case mk a => + induction m₂ + case mk b => + exact sound <| DHashMap.Const.Equiv_of_beq_eq_true h + +end Const + +namespace Const + +@[inline, inherit_doc DHashMap.beq] +def beq_unit [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) : Bool := lift₂ (fun x y : DHashMap α fun _ => Unit => DHashMap.Const.beq x y) + (fun _ _ _ _ => DHashMap.Const.Equiv.beq_congr) m₁ m₂ + +theorem beq_unit_of_eq [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : m₁ = m₂) : Const.beq m₁ m₂ := by + apply beq_of_eq + exact h + +theorem eq_of_beq_unit_eq_true [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : Const.beq m₁ m₂) : m₁ = m₂ := by + apply eq_of_beq_eq_true + exact h + +end Const @[inline, inherit_doc DHashMap.Const.unitOfArray] def Const.unitOfArray [BEq α] [Hashable α] (l : Array α) : diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index 838f55494b52..c31dd0c748b8 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -249,6 +249,25 @@ def union [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashMap α β) : Ext instance [EquivBEq α] [LawfulHashable α] : Union (ExtHashMap α β) := ⟨union⟩ +@[inline, inherit_doc ExtDHashMap.beq] +def beq [LawfulBEq α] [BEq β] (m₁ m₂ : ExtHashMap α β) : Bool := ExtDHashMap.Const.beq m₁.inner m₂.inner + +instance [LawfulBEq α] [BEq β] : BEq (ExtHashMap α β) := ⟨beq⟩ + +instance [LawfulBEq α] [BEq β] [ReflBEq β] : ReflBEq (ExtHashMap α β) where + rfl := by intro a; apply ExtDHashMap.Const.beq_of_eq; rfl + +instance [LawfulBEq α] [BEq β] [LawfulBEq β] : LawfulBEq (ExtHashMap α β) where + eq_of_beq := by + intro a b hyp + cases a + case mk a₀ => + cases b + case mk b₀ => + simp only [mk.injEq] + apply ExtDHashMap.Const.eq_of_beq_eq_true + exact hyp + @[inline, inherit_doc ExtDHashMap.Const.unitOfArray] def unitOfArray [BEq α] [Hashable α] (l : Array α) : ExtHashMap α Unit := From 7ed80a983d1c4434e64e053c825951e908eafcb2 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 27 Nov 2025 11:07:58 +0000 Subject: [PATCH 20/72] Add BEq to ExtHashSet --- src/Std/Data/ExtDHashMap/Basic.lean | 4 ++-- src/Std/Data/ExtHashSet/Basic.lean | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index 61bf6a3a3d0b..93378b6e7ed8 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -416,11 +416,11 @@ namespace Const def beq_unit [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) : Bool := lift₂ (fun x y : DHashMap α fun _ => Unit => DHashMap.Const.beq x y) (fun _ _ _ _ => DHashMap.Const.Equiv.beq_congr) m₁ m₂ -theorem beq_unit_of_eq [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : m₁ = m₂) : Const.beq m₁ m₂ := by +theorem beq_unit_of_eq [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : m₁ = m₂) : Const.beq_unit m₁ m₂ := by apply beq_of_eq exact h -theorem eq_of_beq_unit_eq_true [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : Const.beq m₁ m₂) : m₁ = m₂ := by +theorem eq_of_beq_unit_eq_true [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : Const.beq_unit m₁ m₂) : m₁ = m₂ := by apply eq_of_beq_eq_true exact h diff --git a/src/Std/Data/ExtHashSet/Basic.lean b/src/Std/Data/ExtHashSet/Basic.lean index 830efa81bb82..a72c6b473e4a 100644 --- a/src/Std/Data/ExtHashSet/Basic.lean +++ b/src/Std/Data/ExtHashSet/Basic.lean @@ -204,6 +204,35 @@ def union [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashSet α) : ExtHas instance [EquivBEq α] [LawfulHashable α] : Union (ExtHashSet α) := ⟨union⟩ +@[inline, inherit_doc ExtHashMap.beq] +def beq [LawfulBEq α] (m₁ m₂ : ExtHashSet α) : Bool := ExtDHashMap.Const.beq_unit m₁.inner.inner m₂.inner.inner + +instance [LawfulBEq α] : BEq (ExtHashSet α) := ⟨beq⟩ + +instance [LawfulBEq α] : ReflBEq (ExtHashSet α) where + rfl := by + intro a + cases a + case mk a => + apply ExtDHashMap.Const.beq_unit_of_eq + rfl + +instance [LawfulBEq α] : LawfulBEq (ExtHashSet α) where + eq_of_beq := by + intro a b hyp + cases a + case mk a₀ => + cases b + case mk b₀ => + cases a₀ + case mk a₁ => + cases b₀ + case mk b₁ => + simp only [mk.injEq, ExtHashMap.mk.injEq] + simp only [BEq.beq, beq] at hyp + apply ExtDHashMap.Const.eq_of_beq_unit_eq_true + · exact hyp + /-- Creates a hash set from an array of elements. Note that unlike repeatedly calling `insert`, if the collection contains multiple elements that are equal (with regard to `==`), then the last element From 4a93e11e1c2f9b6415b30b1acf0cccfc5cfb5920 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 27 Nov 2025 11:26:52 +0000 Subject: [PATCH 21/72] Fix merge issue --- src/Std/Data/ExtDHashMap/Basic.lean | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index 0568dae3c593..c4435a9a1d87 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -360,6 +360,8 @@ def union [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtDHashMap α β) : Ex . exact equiv₁ . exact equiv₂) m₁ m₂ +instance [EquivBEq α] [LawfulHashable α] : Union (ExtDHashMap α β) := ⟨union⟩ + @[inline, inherit_doc DHashMap.beq] def beq [LawfulBEq α] [∀ k, BEq (β k)] (m₁ m₂ : ExtDHashMap α β) : Bool := lift₂ (fun x y : DHashMap α β => x.beq y) (fun _ _ _ _ => DHashMap.Equiv.beq_congr) m₁ m₂ From 59a0ec61c1ab0cb1622fb05975b4cc415a13e825 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 27 Nov 2025 14:23:33 +0000 Subject: [PATCH 22/72] Remove unnecessary hashable instance --- src/Std/Data/Internal/List/Associative.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index b27c4e2b8128..64fed986011e 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -258,7 +258,7 @@ end else getValueCast? a l /-- Internal implementation detail of the hash map -/ -def beqModel [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] (l₁ l₂ : List ((a : α) × β a)) := +def beqModel [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] (l₁ l₂ : List ((a : α) × β a)) := if l₁.length ≠ l₂.length then false else (l₁.all fun x => getValueCast? x.fst l₂ == some x.snd) @[simp] theorem getValueCast?_nil [BEq α] [LawfulBEq α] {a : α} : From 53e46533258445d6663135bc74d84eca8c9ed323 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 27 Nov 2025 14:32:44 +0000 Subject: [PATCH 23/72] Remove unnecessary hashable --- src/Std/Data/Internal/List/Associative.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 64fed986011e..d5d472e48796 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -290,7 +290,7 @@ section variable {β : Type v} /-- Internal implementation detail of the hash map -/ -def Const.beqModel [BEq α] [Hashable α] [BEq β] (l₁ l₂ : List ((_ : α) × β)) := +def Const.beqModel [BEq α] [BEq β] (l₁ l₂ : List ((_ : α) × β)) := if l₁.length ≠ l₂.length then false else (l₁.all fun x => getValue? x.fst l₂ == some x.snd) /-- This is a strange dependent version of `Option.map` in which the mapping function is allowed to From cea11fe836bc56a0639fb2b1aa5fa0fa3d1586cd Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 27 Nov 2025 15:06:03 +0000 Subject: [PATCH 24/72] Continue removing useless Hashable instance --- src/Std/Data/Internal/List/Associative.lean | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index d5d472e48796..8a24f179fd1b 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -6714,7 +6714,7 @@ theorem isEmpty_filter_key_iff [BEq α] [EquivBEq α] {f : α → Bool} simp only [getKey, getKey?_eq_getEntry?, this] at h exact h -theorem beqModel_eq_true_of_perm [BEq α] [Hashable α] [LawfulBEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → beqModel l₁ l₂ := by +theorem beqModel_eq_true_of_perm [BEq α] [LawfulBEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → beqModel l₁ l₂ := by intro hyp rw [beqModel] split @@ -6734,7 +6734,7 @@ theorem beqModel_eq_true_of_perm [BEq α] [Hashable α] [LawfulBEq α] [LawfulB symm apply getValueCast?_of_perm hl₁ hyp -theorem Const.beqModel_eq_true_of_perm {β : Type v} [BEq α] [EquivBEq α] [Hashable α] [BEq β] [ReflBEq β] {l₁ l₂ : List ((_ : α) × β )} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → Const.beqModel l₁ l₂ := by +theorem Const.beqModel_eq_true_of_perm {β : Type v} [BEq α] [EquivBEq α] [BEq β] [ReflBEq β] {l₁ l₂ : List ((_ : α) × β )} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → Const.beqModel l₁ l₂ := by intro hyp rw [beqModel] split @@ -6756,7 +6756,7 @@ theorem Const.beqModel_eq_true_of_perm {β : Type v} [BEq α] [EquivBEq α] [Has · exact hl₁ · exact hc -theorem perm_of_beqModel [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : +theorem perm_of_beqModel [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : beqModel l₁ l₂ → l₁.Perm l₂ := by rw [beqModel] split @@ -6806,7 +6806,7 @@ theorem all_congr [BEq α] {l₁ l₂ : List ((a : α) × β a)} {f : (a : α) · intro hyp ⟨k,v⟩ mem exact hyp ⟨k,v⟩ (@Perm.mem_iff _ ⟨k,v⟩ l₂ l₁ hp.symm |>.2 mem) -theorem beqModel_congr [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] {l₁ l₂ l₃ l₄ : List ((a : α) × β a)} +theorem beqModel_congr [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] {l₁ l₂ l₃ l₄ : List ((a : α) × β a)} (hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by rw [beqModel] split @@ -6828,7 +6828,7 @@ theorem beqModel_congr [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] rw [this] apply all_congr p₁ -theorem Const.beqModel_congr {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] [BEq β] {l₁ l₂ l₃ l₄ : List ((_ : α) × β)} +theorem Const.beqModel_congr {β : Type v} [BEq α] [LawfulBEq α] [BEq β] {l₁ l₂ l₃ l₄ : List ((_ : α) × β)} (hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by rw [beqModel] split @@ -6850,13 +6850,13 @@ theorem Const.beqModel_congr {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] rw [this] apply all_congr p₁ -theorem beqModel_eq_beqModel_const {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] [BEq β] {l₁ l₂ : List ((_ : α) × β)} : beqModel l₁ l₂ = Const.beqModel l₁ l₂ := by +theorem beqModel_eq_beqModel_const {β : Type v} [BEq α] [LawfulBEq α] [BEq β] {l₁ l₂ : List ((_ : α) × β)} : beqModel l₁ l₂ = Const.beqModel l₁ l₂ := by rw [beqModel, Const.beqModel] congr ext x rw [getValue?_eq_getValueCast?] -theorem Const.perm_of_beqModel {β : Type v} [BEq α] [Hashable α] [LawfulBEq α] [BEq β] [LawfulBEq β] {l₁ l₂ : List ((_ : α) × β)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : +theorem Const.perm_of_beqModel {β : Type v} [BEq α] [LawfulBEq α] [BEq β] [LawfulBEq β] {l₁ l₂ : List ((_ : α) × β)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : beqModel l₁ l₂ → l₁.Perm l₂ := by rw [← beqModel_eq_beqModel_const] intro hyp From a87d1e0ae5b152ec04f913c327322879afbe2a0b Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 27 Nov 2025 15:07:51 +0000 Subject: [PATCH 25/72] Remove whitespace --- src/Std/Data/Internal/List/Associative.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 8a24f179fd1b..b67036e925bc 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -6714,7 +6714,7 @@ theorem isEmpty_filter_key_iff [BEq α] [EquivBEq α] {f : α → Bool} simp only [getKey, getKey?_eq_getEntry?, this] at h exact h -theorem beqModel_eq_true_of_perm [BEq α] [LawfulBEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → beqModel l₁ l₂ := by +theorem beqModel_eq_true_of_perm [BEq α] [LawfulBEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → beqModel l₁ l₂ := by intro hyp rw [beqModel] split From 59738d1c1d792dabc14eeaa4d66c61ba536ac739 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 27 Nov 2025 16:58:21 +0000 Subject: [PATCH 26/72] Fix formatting --- src/Std/Data/ExtHashMap/Basic.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index 55642133d506..95a0f9c8a6c4 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -267,6 +267,7 @@ instance [LawfulBEq α] [BEq β] [LawfulBEq β] : LawfulBEq (ExtHashMap α β) w simp only [mk.injEq] apply ExtDHashMap.Const.eq_of_beq_eq_true exact hyp + @[inline, inherit_doc ExtDHashMap.inter] def inter [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashMap α β) : ExtHashMap α β := ⟨ExtDHashMap.inter m₁.inner m₂.inner⟩ From 8a84316d4640582fb7a7f5de5605245248e8afe0 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 27 Nov 2025 17:08:12 +0000 Subject: [PATCH 27/72] Remove unused code --- src/Std/Data/DHashMap/Raw.lean | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Std/Data/DHashMap/Raw.lean b/src/Std/Data/DHashMap/Raw.lean index de8872111409..65ddebb87658 100644 --- a/src/Std/Data/DHashMap/Raw.lean +++ b/src/Std/Data/DHashMap/Raw.lean @@ -533,16 +533,6 @@ def Const.beq {β : Type v} [BEq α] [Hashable α] [BEq β] (m₁ m₂ : Raw α else false -/-- Internal implementation detail of the hash map. -/ -def Const.beq_const [BEq α] [Hashable α] (m₁ m₂ : Raw α (fun _ => Unit)) : Bool := - if h₁ : 0 < m₁.buckets.size then - if h₂ : 0 < m₂.buckets.size then - Raw₀.Const.beq ⟨m₁, h₁⟩ ⟨m₂, h₂⟩ - else - false - else - false - /-- Computes the difference of the given hash maps. From ba95c26fc9385cdcf74678a93552d828878af4ab Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 28 Nov 2025 13:46:58 +0000 Subject: [PATCH 28/72] Initial work --- src/Std/Data/DHashMap.lean | 1 + src/Std/Data/DHashMap/DecidableEq.lean | 34 +++++++++++++++++++ src/Std/Data/DHashMap/Internal/RawLemmas.lean | 13 +++++++ src/Std/Data/ExtDHashMap/DecidableEq.lean | 34 +++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 src/Std/Data/DHashMap/DecidableEq.lean create mode 100644 src/Std/Data/ExtDHashMap/DecidableEq.lean diff --git a/src/Std/Data/DHashMap.lean b/src/Std/Data/DHashMap.lean index 03860f758875..64f53f3dfe8e 100644 --- a/src/Std/Data/DHashMap.lean +++ b/src/Std/Data/DHashMap.lean @@ -11,3 +11,4 @@ public import Std.Data.DHashMap.AdditionalOperations public import Std.Data.DHashMap.Iterator public import Std.Data.DHashMap.Lemmas public import Std.Data.DHashMap.IteratorLemmas +public import Std.Data.DHashMap.DecidableEq diff --git a/src/Std/Data/DHashMap/DecidableEq.lean b/src/Std/Data/DHashMap/DecidableEq.lean new file mode 100644 index 000000000000..b2231c98d44c --- /dev/null +++ b/src/Std/Data/DHashMap/DecidableEq.lean @@ -0,0 +1,34 @@ +/- +Copyright (c) 2024 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wojciech Różowski +-/ +module + +prelude +public import Std.Data.DHashMap.Internal.RawLemmas +import all Std.Data.DHashMap.Basic +public import Std.Data.DHashMap.AdditionalOperations +import all Std.Data.DHashMap.AdditionalOperations + +public section + +/-! +# Decidable equality for DHashMaps +-/ + +open Std.DHashMap.Internal + + +namespace Std.DHashMap + +variable {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) + +def Equiv.decide : Decidable (m₁ ~m m₂) := + @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| + @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 + +instance : Decidable (m₁ ~m m₂) := Equiv.decide m₁ m₂ + + +end Std.DHashMap diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 0cc654cea55c..bc5e5716f370 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -5136,4 +5136,17 @@ end map end Raw₀ +namespace Raw₀ + +/-- Internal implementation detail -/ +def Equiv.decide [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] + (m₁ m₂ : Raw₀ α β) (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : Decidable (m₁.1.Equiv m₂.1) := by + have decBEq : Decidable (Raw₀.beq m₁ m₂ = true) := inferInstance + apply @decidable_of_decidable_of_iff (Raw₀.beq m₁ m₂ = true) (m₁.1.Equiv m₂.1) decBEq + constructor + · apply Raw₀.Equiv_of_beq_eq_true h₁ h₂ + · apply Raw₀.Equiv.beq h₁ h₂ + +end Raw₀ + end Std.DHashMap.Internal diff --git a/src/Std/Data/ExtDHashMap/DecidableEq.lean b/src/Std/Data/ExtDHashMap/DecidableEq.lean new file mode 100644 index 000000000000..95385e64076e --- /dev/null +++ b/src/Std/Data/ExtDHashMap/DecidableEq.lean @@ -0,0 +1,34 @@ +module + +prelude +public import Std.Data.ExtDHashMap.Basic +public import Std.Data.ExtDHashMap.Lemmas +public import Std.Data.DHashMap.DecidableEq + +public section +namespace Std.ExtDHashMap + +open scoped Std.DHashMap + +variable {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : ExtDHashMap α β) + +def decidableEq : Decidable (m₁ = m₂) := by + have decBEq : Decidable (beq m₁ m₂ = true) := inferInstance + apply @decidable_of_decidable_of_iff (beq m₁ m₂ = true) (m₁ = m₂) decBEq + constructor + case mp => + induction m₁ + case mk a => + induction m₂ + case mk b => + intro hyp + apply sound + apply DHashMap.Equiv_of_beq_eq_true + simp [BEq.beq] + sorry + case mpr => + sorry + + + +end Std.ExtDHashMap From 109af27852760cf6accc904bd4a6c31fbb668db5 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 28 Nov 2025 13:47:23 +0000 Subject: [PATCH 29/72] Add import --- src/Std/Data/ExtDHashMap.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Std/Data/ExtDHashMap.lean b/src/Std/Data/ExtDHashMap.lean index 2830bb050c79..e0044d193d8a 100644 --- a/src/Std/Data/ExtDHashMap.lean +++ b/src/Std/Data/ExtDHashMap.lean @@ -8,3 +8,4 @@ module prelude public import Std.Data.ExtDHashMap.Basic public import Std.Data.ExtDHashMap.Lemmas +public import Std.Data.ExtDHashMap.DecidableEq From b928c86853b1684624e1bc32bd41875900733d49 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 28 Nov 2025 17:50:30 +0000 Subject: [PATCH 30/72] Refactor ExtDHashMap code --- src/Std/Data/ExtDHashMap/Basic.lean | 30 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index c4435a9a1d87..bcd4e271f082 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -368,23 +368,25 @@ def beq [LawfulBEq α] [∀ k, BEq (β k)] (m₁ m₂ : ExtDHashMap α β) : Boo instance [LawfulBEq α] [∀ k, BEq (β k)] : BEq (ExtDHashMap α β) := ⟨beq⟩ +theorem beq_of_eq [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] (m₁ m₂ : ExtDHashMap α β) (hyp : m₁ = m₂) : m₁ == m₂ := by + induction m₁ + case mk a => + induction m₂ + case mk b => + exact DHashMap.Equiv.beq <| exact hyp + +theorem eq_of_beq_true [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] (m₁ m₂ : ExtDHashMap α β) (hyp : (m₁ == m₂) = true) : m₁ = m₂ := by + induction m₁ + case mk a => + induction m₂ + case mk b => + apply sound <| DHashMap.Equiv_of_beq_eq_true hyp + instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : ReflBEq (ExtDHashMap α β) where - rfl := by - intro a - induction a - case mk a => - simp only [BEq.beq, beq] - apply DHashMap.Equiv.beq - apply DHashMap.Equiv.refl + rfl {a} := by apply beq_of_eq; rfl instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : LawfulBEq (ExtDHashMap α β) where - eq_of_beq := by - intro a b hyp - induction a - case mk a₀ => - induction b - case mk b₀ => - apply sound <| DHashMap.Equiv_of_beq_eq_true hyp + eq_of_beq := fun hyp => ExtDHashMap.eq_of_beq_true _ _ hyp namespace Const From 483f612626218def8ce3aaf37572d468f547b07a Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 28 Nov 2025 17:55:59 +0000 Subject: [PATCH 31/72] One more refactor --- src/Std/Data/ExtDHashMap/Basic.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index bcd4e271f082..ab2ec77873e7 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -386,7 +386,7 @@ instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : ReflBEq (E rfl {a} := by apply beq_of_eq; rfl instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : LawfulBEq (ExtDHashMap α β) where - eq_of_beq := fun hyp => ExtDHashMap.eq_of_beq_true _ _ hyp + eq_of_beq := fun hyp => eq_of_beq_true _ _ hyp namespace Const From c7773607f3bea39d03a201e091baedc1201d5b7d Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 28 Nov 2025 18:04:39 +0000 Subject: [PATCH 32/72] Finish decidableEq instance for ExtDHashMap --- src/Std/Data/ExtDHashMap/DecidableEq.lean | 24 +++++++---------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/Std/Data/ExtDHashMap/DecidableEq.lean b/src/Std/Data/ExtDHashMap/DecidableEq.lean index 95385e64076e..a0afe0bc2194 100644 --- a/src/Std/Data/ExtDHashMap/DecidableEq.lean +++ b/src/Std/Data/ExtDHashMap/DecidableEq.lean @@ -1,3 +1,8 @@ +/- +Copyright (c) 2024 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wojciech Różowski +-/ module prelude @@ -12,23 +17,8 @@ open scoped Std.DHashMap variable {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : ExtDHashMap α β) -def decidableEq : Decidable (m₁ = m₂) := by - have decBEq : Decidable (beq m₁ m₂ = true) := inferInstance - apply @decidable_of_decidable_of_iff (beq m₁ m₂ = true) (m₁ = m₂) decBEq - constructor - case mp => - induction m₁ - case mk a => - induction m₂ - case mk b => - intro hyp - apply sound - apply DHashMap.Equiv_of_beq_eq_true - simp [BEq.beq] - sorry - case mpr => - sorry - +def decidableEq : Decidable (m₁ = m₂) := @decidable_of_decidable_of_iff _ _ _ ⟨by apply ExtDHashMap.eq_of_beq_true, by apply ExtDHashMap.beq_of_eq⟩ +instance : DecidableEq (ExtDHashMap α β) := decidableEq end Std.ExtDHashMap From d1f18b94f64891314e09e18eb1b939ad6ca96133 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 13:29:29 +0000 Subject: [PATCH 33/72] First part of addressing Markus' comments --- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 8 ++++---- src/Std/Data/DHashMap/Internal/WF.lean | 4 ++-- src/Std/Data/DHashMap/Lemmas.lean | 8 ++++---- src/Std/Data/DHashMap/Raw.lean | 1 - src/Std/Data/DHashMap/RawLemmas.lean | 10 +++++----- src/Std/Data/ExtDHashMap/Basic.lean | 4 ++-- src/Std/Data/HashMap/Lemmas.lean | 4 ++-- src/Std/Data/HashMap/RawLemmas.lean | 4 ++-- src/Std/Data/HashSet/Lemmas.lean | 4 ++-- src/Std/Data/HashSet/RawLemmas.lean | 4 ++-- src/Std/Data/Internal/List/Associative.lean | 8 ++++---- 11 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 0cc654cea55c..c10d055d6e3f 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -164,8 +164,8 @@ private meta def queryMap : Std.DHashMap Name (fun _ => Name × Array (MacroM (T ⟨`getEntryD, (``getEntryD_eq_getEntryD, #[`(getEntryD_of_perm _)])⟩, ⟨`getEntry!, (``getEntry!_eq_getEntry!, #[`(getEntry!_of_perm _)])⟩, ⟨`toList, (``Raw.toList_eq_toListModel, #[])⟩, - ⟨`Const.beq, (``Raw₀.Const.toListModel_beq, #[])⟩, - ⟨`beq, (``toListModel_beq, #[])⟩, + ⟨`Const.beq, (``Raw₀.Const.beq_eq_beqModel, #[])⟩, + ⟨`beq, (``beq_eq_beqModel, #[])⟩, ⟨`keys, (``Raw.keys_eq_keys_toListModel, #[`(perm_keys_congr_left)])⟩, ⟨`Const.toList, (``Raw.Const.toList_eq_toListModel_map, #[`(perm_map_congr_left)])⟩, ⟨`foldM, (``Raw.foldM_eq_foldlM_toListModel, #[])⟩, @@ -2590,7 +2590,7 @@ variable {m₁ m₂ : Raw₀ α β} [LawfulBEq α] [∀ k, BEq (β k)] theorem Equiv.beq [∀ k, ReflBEq (β k)] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : m₁.1.Equiv m₂.1 → beq m₁ m₂ := by simp_to_model using List.beqModel_eq_true_of_perm -theorem Equiv_of_beq_eq_true [∀ k, LawfulBEq (β k)] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ = true → m₁.1.Equiv m₂.1 := by +theorem equiv_of_beq [∀ k, LawfulBEq (β k)] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ = true → m₁.1.Equiv m₂.1 := by simp_to_model using List.perm_of_beqModel theorem Equiv.beq_congr {m₃ m₄ : Raw₀ α β} (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) (h₃ : m₃.val.WF) (h₄ : m₄.val.WF) : @@ -2606,7 +2606,7 @@ variable {β : Type v} {m₁ m₂ : Raw₀ α (fun _ => β)} theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : m₁.1.Equiv m₂.1 → Const.beq m₁ m₂ := by simp_to_model using List.Const.beqModel_eq_true_of_perm -theorem Const.Equiv_of_beq_eq_true [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ = true → m₁.1.Equiv m₂.1 := by +theorem Const.equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ = true → m₁.1.Equiv m₂.1 := by simp_to_model using List.Const.perm_of_beqModel theorem Const.Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : Raw₀ α (fun _ => β)} [BEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) (h₃ : m₃.val.WF) (h₄ : m₄.val.WF) : diff --git a/src/Std/Data/DHashMap/Internal/WF.lean b/src/Std/Data/DHashMap/Internal/WF.lean index 441c8f632f4d..0ec2f5e85559 100644 --- a/src/Std/Data/DHashMap/Internal/WF.lean +++ b/src/Std/Data/DHashMap/Internal/WF.lean @@ -1597,7 +1597,7 @@ theorem Const.wf_insertManyIfNewUnit₀ [BEq α] [Hashable α] [EquivBEq α] [La {l : ρ} (h' : m.WF) : (Const.insertManyIfNewUnit ⟨m, h⟩ l).1.1.WF := (Raw₀.Const.insertManyIfNewUnit ⟨m, h⟩ l).2 _ Raw.WF.insertIfNew₀ h' -theorem toListModel_beq [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] {m₁ m₂ : Raw₀ α β} (h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) : +theorem beq_eq_beqModel [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] {m₁ m₂ : Raw₀ α β} (h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) : beq m₁ m₂ = beqModel m₁.1.toList m₂.1.toList := by rw [beq, beqModel] split @@ -1616,7 +1616,7 @@ theorem toListModel_beq [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k) · exact h₂ · exact h₁ -theorem Const.toListModel_beq {β : Type v} [BEq α] [PartialEquivBEq α] [Hashable α] [LawfulHashable α] [BEq β] {m₁ m₂ : Raw₀ α (fun _ => β)} (h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) : +theorem Const.beq_eq_beqModel {β : Type v} [BEq α] [PartialEquivBEq α] [Hashable α] [LawfulHashable α] [BEq β] {m₁ m₂ : Raw₀ α (fun _ => β)} (h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) : beq m₁ m₂ = Const.beqModel m₁.1.toList m₂.1.toList := by rw [beq, Const.beqModel] split diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index 2556e2dda622..2597749d8703 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -1845,9 +1845,9 @@ theorem Equiv.beq [∀ k, ReflBEq (β k)] (h : m₁ ~m m₂) : m₁ == m₂ := b simp [BEq.beq] apply Raw₀.Equiv.beq m₁.2 m₂.2 h.1 -theorem Equiv_of_beq_eq_true [∀ k, LawfulBEq (β k)] (h : m₁ == m₂) : m₁ ~m m₂ := by +theorem equiv_of_beq [∀ k, LawfulBEq (β k)] (h : m₁ == m₂) : m₁ ~m m₂ := by constructor - have := @Raw₀.Equiv_of_beq_eq_true α β _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h + have := @Raw₀.equiv_of_beq α β _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h simp only at this exact this @@ -1862,9 +1862,9 @@ variable {β : Type v} {m₁ m₂ : DHashMap α (fun _ => β)} [BEq β] theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [ReflBEq β] (h : m₁ ~m m₂) : DHashMap.Const.beq m₁ m₂ := by apply Raw₀.Const.Equiv.beq m₁.2 m₂.2 h.1 -theorem Const.Equiv_of_beq_eq_true [LawfulBEq α] [LawfulBEq β] (h : Const.beq m₁ m₂) : m₁ ~m m₂ := by +theorem Const.equiv_of_beq [LawfulBEq α] [LawfulBEq β] (h : Const.beq m₁ m₂) : m₁ ~m m₂ := by constructor - have := @Raw₀.Const.Equiv_of_beq_eq_true α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h + have := @Raw₀.Const.equiv_of_beq α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h simp only at this exact this diff --git a/src/Std/Data/DHashMap/Raw.lean b/src/Std/Data/DHashMap/Raw.lean index 65ddebb87658..e9fac297b12e 100644 --- a/src/Std/Data/DHashMap/Raw.lean +++ b/src/Std/Data/DHashMap/Raw.lean @@ -548,7 +548,6 @@ This function always iterates through the smaller map, so the expected runtime i else m₂ - instance [BEq α] [Hashable α] : SDiff (Raw α β) := ⟨diff⟩ section Unverified diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index 4f064ffd9a2c..de5b0dcf75a9 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -47,7 +47,7 @@ private meta def baseNames : Array Name := ``getKey?_eq, ``getKey_eq, ``getKey!_eq, ``getKeyD_eq, ``insertMany_eq, ``Const.insertMany_eq, ``Const.insertManyIfNewUnit_eq, ``ofArray_eq, ``Const.ofArray_eq, ``ofList_eq, ``Const.ofList_eq, ``Const.unitOfList_eq, ``Const.unitOfArray_eq, - ``alter_eq, ``Const.alter_eq, ``modify_eq, ``Const.modify_eq, ``union_eq, ``inter_eq, `diff_eq, ``beq_eq, ``Const.beq_eq] + ``alter_eq, ``Const.alter_eq, ``modify_eq, ``Const.modify_eq, ``union_eq, ``inter_eq, ``diff_eq, ``beq_eq, ``Const.beq_eq] /-- Internal implementation detail of the hash map -/ @@ -3766,8 +3766,8 @@ theorem Equiv.beq [∀ k, ReflBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) : m intro h exact Raw₀.Equiv.beq h₁ h₂ h -theorem Equiv_of_beq_eq_true [∀ k, LawfulBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) : beq m₁ m₂ = true → m₁ ~m m₂ := by - simp_to_raw using Raw₀.Equiv_of_beq_eq_true +theorem equiv_of_beq [∀ k, LawfulBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) : beq m₁ m₂ = true → m₁ ~m m₂ := by + simp_to_raw using Raw₀.equiv_of_beq theorem Equiv.beq_congr {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : m₁ ~m m₃ → m₂ ~m m₄ → Raw.beq m₁ m₂ = Raw.beq m₃ m₄ := by @@ -3785,8 +3785,8 @@ theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] intro h exact Raw₀.Const.Equiv.beq h₁ h₂ h -theorem Const.Equiv_of_beq_eq_true [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : beq m₁ m₂ = true → m₁ ~m m₂ := by - simp_to_raw using Raw₀.Const.Equiv_of_beq_eq_true +theorem Const.equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : beq m₁ m₂ = true → m₁ ~m m₂ := by + simp_to_raw using Raw₀.Const.equiv_of_beq theorem Const.Equiv.beq_congr [LawfulBEq α] [BEq β] {m₃ m₄ : Raw α (fun _ => β)} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : m₁ ~m m₃ → m₂ ~m m₄ → Raw.Const.beq m₁ m₂ = Raw.Const.beq m₃ m₄ := by diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index ab2ec77873e7..0c4279f9d783 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -380,7 +380,7 @@ theorem eq_of_beq_true [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β case mk a => induction m₂ case mk b => - apply sound <| DHashMap.Equiv_of_beq_eq_true hyp + apply sound <| DHashMap.equiv_of_beq hyp instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : ReflBEq (ExtDHashMap α β) where rfl {a} := by apply beq_of_eq; rfl @@ -407,7 +407,7 @@ theorem eq_of_beq_eq_true [LawfulBEq α] [BEq β] [LawfulBEq β] (m₁ m₂ : Ex case mk a => induction m₂ case mk b => - exact sound <| DHashMap.Const.Equiv_of_beq_eq_true h + exact sound <| DHashMap.Const.equiv_of_beq h end Const diff --git a/src/Std/Data/HashMap/Lemmas.lean b/src/Std/Data/HashMap/Lemmas.lean index 46c903e72cea..423b6469f48c 100644 --- a/src/Std/Data/HashMap/Lemmas.lean +++ b/src/Std/Data/HashMap/Lemmas.lean @@ -1352,8 +1352,8 @@ variable {β : Type v} {m₁ m₂ : HashMap α β} [BEq β] theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [ReflBEq β] (h : m₁ ~m m₂) : m₁ == m₂ := DHashMap.Const.Equiv.beq h.1 -theorem Equiv_of_beq_eq_true [LawfulBEq α] [LawfulBEq β] (h : m₁ == m₂) : m₁ ~m m₂ := - ⟨DHashMap.Const.Equiv_of_beq_eq_true h⟩ +theorem equiv_of_beq [LawfulBEq α] [LawfulBEq β] (h : m₁ == m₂) : m₁ ~m m₂ := + ⟨DHashMap.Const.equiv_of_beq h⟩ theorem Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : HashMap α β} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun h1 h2 => DHashMap.Const.Equiv.beq_congr h1.1 h2.1 diff --git a/src/Std/Data/HashMap/RawLemmas.lean b/src/Std/Data/HashMap/RawLemmas.lean index 886315b2ef95..484b9aafe82e 100644 --- a/src/Std/Data/HashMap/RawLemmas.lean +++ b/src/Std/Data/HashMap/RawLemmas.lean @@ -1314,8 +1314,8 @@ variable {β : Type v} {m₁ m₂ : Raw α β} theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := fun hyp => @DHashMap.Raw.Const.Equiv.beq _ _ _ _ m₁.1 m₂.1 _ _ _ _ h₁.1 h₂.1 hyp.1 -theorem Equiv_of_beq_eq_true [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := fun hyp => - ⟨@DHashMap.Raw.Const.Equiv_of_beq_eq_true _ _ _ _ m₁.1 m₂.1 _ _ _ h₁.1 h₂.1 hyp⟩ +theorem equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := fun hyp => + ⟨@DHashMap.Raw.Const.equiv_of_beq _ _ _ _ m₁.1 m₂.1 _ _ _ h₁.1 h₂.1 hyp⟩ theorem Equiv.beq_congr [LawfulBEq α] [BEq β] {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun hyp1 hyp2 => diff --git a/src/Std/Data/HashSet/Lemmas.lean b/src/Std/Data/HashSet/Lemmas.lean index 76e8d7f69ec1..f54aa8f59ee1 100644 --- a/src/Std/Data/HashSet/Lemmas.lean +++ b/src/Std/Data/HashSet/Lemmas.lean @@ -788,8 +788,8 @@ variable {m₁ m₂ : HashSet α} theorem Equiv.beq [LawfulHashable α] [EquivBEq α] (h : m₁ ~m m₂) : m₁ == m₂ := HashMap.Equiv.beq h.1 -theorem Equiv_of_beq_eq_true [LawfulBEq α] (h : m₁ == m₂) : m₁ ~m m₂ := - ⟨HashMap.Equiv_of_beq_eq_true h⟩ +theorem equiv_of_beq [LawfulBEq α] (h : m₁ == m₂) : m₁ ~m m₂ := + ⟨HashMap.equiv_of_beq h⟩ theorem Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : HashSet α} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun h1 h2 => HashMap.Equiv.beq_congr h1.1 h2.1 diff --git a/src/Std/Data/HashSet/RawLemmas.lean b/src/Std/Data/HashSet/RawLemmas.lean index 10e806036ad4..f8d8742300fc 100644 --- a/src/Std/Data/HashSet/RawLemmas.lean +++ b/src/Std/Data/HashSet/RawLemmas.lean @@ -820,8 +820,8 @@ variable {m₁ m₂ : Raw α} theorem Equiv.beq [LawfulHashable α] [EquivBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := fun hyp => @HashMap.Raw.Equiv.beq _ _ _ _ m₁.1 m₂.1 _ _ _ _ h₁.1 h₂.1 hyp.1 -theorem Equiv_of_beq_eq_true [LawfulBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := fun hyp => - ⟨@HashMap.Raw.Equiv_of_beq_eq_true _ _ _ _ m₁.1 m₂.1 _ _ _ h₁.1 h₂.1 hyp⟩ +theorem equiv_of_beq [LawfulBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := fun hyp => + ⟨@HashMap.Raw.equiv_of_beq _ _ _ _ m₁.1 m₂.1 _ _ _ h₁.1 h₂.1 hyp⟩ theorem Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun hyp1 hyp2 => diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index a121b54d0534..1d5520c7cc7e 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -3577,7 +3577,7 @@ theorem insertList_insertEntry_right_equiv_insertEntry_insertList [BEq α] [Equi . simp only [Option.some_or] . rw [@getEntry?_insertList α β _ _ l toInsert distinct_l (DistinctKeys_impl_Pairwise_distinct distinct_toInsert) a] -theorem length_le_of_keys_subset [BEq α] [EquivBEq α] +theorem length_le_length_of_containsKey [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : α) × β a)} (dl₁ : DistinctKeys l₁) (dl₂ : DistinctKeys l₂) @@ -3625,7 +3625,7 @@ theorem containsKey_of_subset_of_length_eq [BEq α] [EquivBEq α] {l₁ l₂ : L suffices l₁.length < l₂.length by omega suffices l₁.length ≤ (eraseKey a l₂).length ∧ 1 + (eraseKey a l₂).length = l₂.length by omega apply And.intro - · apply length_le_of_keys_subset dl₁ (DistinctKeys.eraseKey dl₂) + · apply length_le_length_of_containsKey dl₁ (DistinctKeys.eraseKey dl₂) intro a₂ mem₂ rw [containsKey_eraseKey dl₂] simp only [Bool.and_eq_true, Bool.not_eq_eq_eq_not, Bool.not_true] @@ -7769,7 +7769,7 @@ theorem Const.beqModel_congr {β : Type v} [BEq α] [LawfulBEq α] [BEq β] {l rw [this] apply all_congr p₁ -theorem beqModel_eq_beqModel_const {β : Type v} [BEq α] [LawfulBEq α] [BEq β] {l₁ l₂ : List ((_ : α) × β)} : beqModel l₁ l₂ = Const.beqModel l₁ l₂ := by +theorem beqModel_eq_constBeqModel {β : Type v} [BEq α] [LawfulBEq α] [BEq β] {l₁ l₂ : List ((_ : α) × β)} : beqModel l₁ l₂ = Const.beqModel l₁ l₂ := by rw [beqModel, Const.beqModel] congr ext x @@ -7777,7 +7777,7 @@ theorem beqModel_eq_beqModel_const {β : Type v} [BEq α] [LawfulBEq α] [BEq β theorem Const.perm_of_beqModel {β : Type v} [BEq α] [LawfulBEq α] [BEq β] [LawfulBEq β] {l₁ l₂ : List ((_ : α) × β)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : beqModel l₁ l₂ → l₁.Perm l₂ := by - rw [← beqModel_eq_beqModel_const] + rw [← beqModel_eq_constBeqModel] intro hyp apply List.perm_of_beqModel · exact hl₁ From dbc9784c450117175a091f3c079c0f4ba7bfa3c3 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 13:34:41 +0000 Subject: [PATCH 34/72] Proof golfing --- src/Std/Data/Internal/List/Associative.lean | 61 ++++++++------------- 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 1d5520c7cc7e..bbb4f350a8c7 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -7635,45 +7635,32 @@ theorem isEmpty_filter_key_iff [BEq α] [EquivBEq α] {f : α → Bool} theorem beqModel_eq_true_of_perm [BEq α] [LawfulBEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → beqModel l₁ l₂ := by intro hyp - rw [beqModel] - split - case isTrue hlen => - rw [ne_eq] at hlen - apply Classical.byContradiction - intro _ - exact hlen <| List.Perm.length_eq hyp - case isFalse hlen => - simp only [List.all_eq_true] - intro ⟨k,v⟩ mem - have hv := getValueCast_of_mem mem hl₁ - have hc := containsKey_of_mem mem - apply beq_of_eq - simp only at |- hc hv - rw [← hv, ← getValueCast?_eq_some_getValueCast] - symm + rw [beqModel, if_neg (by simpa using hyp.length_eq)] + simp only [List.all_eq_true] + intro ⟨k,v⟩ mem + have hv := @getValueCast_of_mem α β _ _ l₁ ⟨k,v⟩ mem + have hc := containsKey_of_mem mem + apply beq_of_eq + simp only at |- hc hv + rw [← hv, ← getValueCast?_eq_some_getValueCast] + · symm apply getValueCast?_of_perm hl₁ hyp + · exact hl₁ theorem Const.beqModel_eq_true_of_perm {β : Type v} [BEq α] [EquivBEq α] [BEq β] [ReflBEq β] {l₁ l₂ : List ((_ : α) × β )} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → Const.beqModel l₁ l₂ := by intro hyp - rw [beqModel] - split - case isTrue hlen => - rw [ne_eq] at hlen - apply Classical.byContradiction - intro _ - exact hlen <| List.Perm.length_eq hyp - case isFalse hlen => - simp only [List.all_eq_true] - intro ⟨k,v⟩ mem - have hv := @getValue_of_mem α β _ _ l₁ ⟨k,v⟩ mem - have hc := containsKey_of_mem mem - apply beq_of_eq - simp only at |- hc hv - rw [← hv, ← getValue?_eq_some_getValue] - · symm - apply getValue?_of_perm hl₁ hyp - · exact hl₁ - · exact hc + rw [beqModel, if_neg (by simpa using hyp.length_eq)] + simp only [List.all_eq_true] + intro ⟨k,v⟩ mem + have hv := @getValue_of_mem α β _ _ l₁ ⟨k,v⟩ mem + have hc := containsKey_of_mem mem + apply beq_of_eq + simp only at |- hc hv + rw [← hv, ← getValue?_eq_some_getValue] + · symm + apply getValue?_of_perm hl₁ hyp + · exact hl₁ + · exact hc theorem perm_of_beqModel [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : beqModel l₁ l₂ → l₁.Perm l₂ := by @@ -7726,7 +7713,7 @@ theorem all_congr [BEq α] {l₁ l₂ : List ((a : α) × β a)} {f : (a : α) exact hyp ⟨k,v⟩ (@Perm.mem_iff _ ⟨k,v⟩ l₂ l₁ hp.symm |>.2 mem) theorem beqModel_congr [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] {l₁ l₂ l₃ l₄ : List ((a : α) × β a)} -(hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by + (hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by rw [beqModel] split case isTrue h => @@ -7748,7 +7735,7 @@ theorem beqModel_congr [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] {l₁ l₂ l apply all_congr p₁ theorem Const.beqModel_congr {β : Type v} [BEq α] [LawfulBEq α] [BEq β] {l₁ l₂ l₃ l₄ : List ((_ : α) × β)} -(hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by + (hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by rw [beqModel] split case isTrue h => From 40ef92e9118d374efa0fec6ee7536b68b535e4d9 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 13:38:04 +0000 Subject: [PATCH 35/72] Fix notation --- src/Std/Data/DHashMap/RawLemmas.lean | 3 ++- src/Std/Data/HashMap/RawLemmas.lean | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index de5b0dcf75a9..920a14123836 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -3761,7 +3761,8 @@ open Internal.Raw Internal.Raw₀ section BEq variable {m₁ m₂ : Raw α β} [LawfulBEq α] [∀ k, BEq (β k)] -theorem Equiv.beq [∀ k, ReflBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := by +theorem Equiv.beq [∀ k, ReflBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → m₁ == m₂ := by + simp only [BEq.beq] simp_to_raw intro h exact Raw₀.Equiv.beq h₁ h₂ h diff --git a/src/Std/Data/HashMap/RawLemmas.lean b/src/Std/Data/HashMap/RawLemmas.lean index 484b9aafe82e..f5da73d93d82 100644 --- a/src/Std/Data/HashMap/RawLemmas.lean +++ b/src/Std/Data/HashMap/RawLemmas.lean @@ -1311,7 +1311,7 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] (h : m.W section variable {β : Type v} {m₁ m₂ : Raw α β} -theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := fun hyp => +theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → m₁ == m₂ := fun hyp => @DHashMap.Raw.Const.Equiv.beq _ _ _ _ m₁.1 m₂.1 _ _ _ _ h₁.1 h₂.1 hyp.1 theorem equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := fun hyp => From b3b2f97831e9200e07502536408ab995b0d459cf Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 13:56:56 +0000 Subject: [PATCH 36/72] Apply Markus' suggestions --- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 5 +- src/Std/Data/DHashMap/Internal/WF.lean | 47 ++++--------------- 2 files changed, 12 insertions(+), 40 deletions(-) diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index c10d055d6e3f..7953f8e8ef8d 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -163,6 +163,7 @@ private meta def queryMap : Std.DHashMap Name (fun _ => Name × Array (MacroM (T ⟨`getEntry?, (``getEntry?_eq_getEntry?, #[`(getEntry?_of_perm _)])⟩, ⟨`getEntryD, (``getEntryD_eq_getEntryD, #[`(getEntryD_of_perm _)])⟩, ⟨`getEntry!, (``getEntry!_eq_getEntry!, #[`(getEntry!_of_perm _)])⟩, + ⟨`all, (``Raw.all_eq_all_toListModel, #[])⟩, ⟨`toList, (``Raw.toList_eq_toListModel, #[])⟩, ⟨`Const.beq, (``Raw₀.Const.beq_eq_beqModel, #[])⟩, ⟨`beq, (``beq_eq_beqModel, #[])⟩, @@ -1455,8 +1456,8 @@ theorem any_eq_false [LawfulBEq α] {p : (a : α) → β a → Bool} (h : m.1.WF omit [Hashable α] [BEq α] in theorem all_toList {p : (a : α) → β a → Bool} : - m.1.toList.all (fun x => p x.1 x.2) = m.1.all p := - DHashMap.Internal.Raw.all_toList + m.1.toList.all (fun x => p x.1 x.2) = m.1.all p := by + simp_to_model omit [Hashable α] [BEq α] in theorem all_eq_not_any_not {p : (a : α) → β a → Bool} : diff --git a/src/Std/Data/DHashMap/Internal/WF.lean b/src/Std/Data/DHashMap/Internal/WF.lean index 0ec2f5e85559..f80d5659f8a9 100644 --- a/src/Std/Data/DHashMap/Internal/WF.lean +++ b/src/Std/Data/DHashMap/Internal/WF.lean @@ -275,8 +275,8 @@ theorem forIn_eq_forIn_toListModel {δ : Type w} {l : Raw α β} {m : Type w → · simp · simpa using ih' -theorem all_toList {p : (a : α) → β a → Bool} {m : Raw α β}: - m.toList.all (fun x => p x.1 x.2) = m.all p := by +theorem all_eq_all_toListModel {p : (a: α) → β a → Bool} {m : Raw α β} : + m.all p = (toListModel m.buckets).all (fun x => p x.1 x.2) := by simp only [Raw.all, ForIn.forIn, Bool.not_eq_true, bind_pure_comp, map_pure, Id.run_bind] rw [forIn_eq_forIn_toListModel, ← toList_eq_toListModel, forIn_eq_forIn'] induction m.toList with @@ -1598,41 +1598,12 @@ theorem Const.wf_insertManyIfNewUnit₀ [BEq α] [Hashable α] [EquivBEq α] [La (Raw₀.Const.insertManyIfNewUnit ⟨m, h⟩ l).2 _ Raw.WF.insertIfNew₀ h' theorem beq_eq_beqModel [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] {m₁ m₂ : Raw₀ α β} (h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) : - beq m₁ m₂ = beqModel m₁.1.toList m₂.1.toList := by - rw [beq, beqModel] - split - case isTrue h => - rw [Raw.size_eq_length, Raw.size_eq_length] at h - rw [Raw.toList_eq_toListModel, Raw.toList_eq_toListModel] - · simp only [ne_eq, h, not_false_eq_true, ↓reduceIte] - · exact h₂ - · exact h₁ - case isFalse h => - rw [Raw.size_eq_length, Raw.size_eq_length] at h - simp [Raw.toList_eq_toListModel, h, ← Raw.all_toList] - congr - · ext x - rw [get?_eq_getValueCast? h₂] - · exact h₂ - · exact h₁ - -theorem Const.beq_eq_beqModel {β : Type v} [BEq α] [PartialEquivBEq α] [Hashable α] [LawfulHashable α] [BEq β] {m₁ m₂ : Raw₀ α (fun _ => β)} (h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) : - beq m₁ m₂ = Const.beqModel m₁.1.toList m₂.1.toList := by - rw [beq, Const.beqModel] - split - case isTrue h => - rw [Raw.size_eq_length, Raw.size_eq_length] at h - rw [Raw.toList_eq_toListModel, Raw.toList_eq_toListModel] - · simp only [ne_eq, h, not_false_eq_true, ↓reduceIte] - · exact h₂ - · exact h₁ - case isFalse h => - rw [Raw.size_eq_length, Raw.size_eq_length] at h - simp [Raw.toList_eq_toListModel, h, ← Raw.all_toList] - congr - · ext x - rw [get?_eq_getValue? h₂] - · exact h₂ - · exact h₁ + beq m₁ m₂ = beqModel (toListModel m₁.1.buckets) (toListModel m₂.1.buckets) := by + simp [beq, beqModel, Raw.size_eq_length h₁, Raw.size_eq_length h₂, Raw.all_eq_all_toListModel, + get?_eq_getValueCast? h₂] + +theorem Const.beq_eq_beqModel {β : Type v} [BEq α] [PartialEquivBEq α] [Hashable α] [LawfulHashable α] [BEq β] {m₁ m₂ : Raw₀ α (fun _ => β)} (h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) : + beq m₁ m₂ = Const.beqModel (toListModel m₁.1.buckets) (toListModel m₂.1.buckets) := by + simp [beq, Const.beqModel, Raw.size_eq_length h₁, Raw.size_eq_length h₂, Raw.all_eq_all_toListModel, get?_eq_getValue? h₂] end Raw₀ From 2b3820f1f45aaed7028d7d4995847f481089860c Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 14:06:16 +0000 Subject: [PATCH 37/72] Resolve semantic merge conflict --- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index c1916f5a028f..82b7f5d43f2a 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -5145,7 +5145,7 @@ def Equiv.decide [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] have decBEq : Decidable (Raw₀.beq m₁ m₂ = true) := inferInstance apply @decidable_of_decidable_of_iff (Raw₀.beq m₁ m₂ = true) (m₁.1.Equiv m₂.1) decBEq constructor - · apply Raw₀.Equiv_of_beq_eq_true h₁ h₂ + · apply Raw₀.equiv_of_beq h₁ h₂ · apply Raw₀.Equiv.beq h₁ h₂ end Raw₀ From c2738a7fa05594508a14a2a7ae5dab0fde9c7c4f Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 14:16:54 +0000 Subject: [PATCH 38/72] Fist portion of Markus' suggestions --- src/Std/Data/DHashMap/DecidableEq.lean | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Std/Data/DHashMap/DecidableEq.lean b/src/Std/Data/DHashMap/DecidableEq.lean index b2231c98d44c..4bfb887579be 100644 --- a/src/Std/Data/DHashMap/DecidableEq.lean +++ b/src/Std/Data/DHashMap/DecidableEq.lean @@ -14,21 +14,14 @@ import all Std.Data.DHashMap.AdditionalOperations public section /-! -# Decidable equality for DHashMaps +# Decidable equivalence for DHashMaps -/ open Std.DHashMap.Internal - namespace Std.DHashMap -variable {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) - -def Equiv.decide : Decidable (m₁ ~m m₂) := - @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 -instance : Decidable (m₁ ~m m₂) := Equiv.decide m₁ m₂ - - end Std.DHashMap From 748a879317dc8728b8d199e1c668c5d7fbbc49be Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 14:25:23 +0000 Subject: [PATCH 39/72] Second part of refactor --- src/Std/Data/DHashMap/DecidableEq.lean | 2 +- src/Std/Data/ExtDHashMap/DecidableEq.lean | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Std/Data/DHashMap/DecidableEq.lean b/src/Std/Data/DHashMap/DecidableEq.lean index 4bfb887579be..eb0dad4de37c 100644 --- a/src/Std/Data/DHashMap/DecidableEq.lean +++ b/src/Std/Data/DHashMap/DecidableEq.lean @@ -14,7 +14,7 @@ import all Std.Data.DHashMap.AdditionalOperations public section /-! -# Decidable equivalence for DHashMaps +# Decidable equivalence for `DHashMap` -/ open Std.DHashMap.Internal diff --git a/src/Std/Data/ExtDHashMap/DecidableEq.lean b/src/Std/Data/ExtDHashMap/DecidableEq.lean index a0afe0bc2194..3c88fa8fbfc1 100644 --- a/src/Std/Data/ExtDHashMap/DecidableEq.lean +++ b/src/Std/Data/ExtDHashMap/DecidableEq.lean @@ -11,14 +11,17 @@ public import Std.Data.ExtDHashMap.Lemmas public import Std.Data.DHashMap.DecidableEq public section + +/-! +# Decidable equality for `ExtDHashMap` +-/ + namespace Std.ExtDHashMap open scoped Std.DHashMap -variable {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : ExtDHashMap α β) - -def decidableEq : Decidable (m₁ = m₂) := @decidable_of_decidable_of_iff _ _ _ ⟨by apply ExtDHashMap.eq_of_beq_true, by apply ExtDHashMap.beq_of_eq⟩ +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] : DecidableEq (ExtDHashMap α β) := + fun m₁ m₂ => @decidable_of_decidable_of_iff (m₁ == m₂) _ _ ⟨by apply ExtDHashMap.eq_of_beq_true, by apply ExtDHashMap.beq_of_eq⟩ -instance : DecidableEq (ExtDHashMap α β) := decidableEq end Std.ExtDHashMap From 0089a8f322155040df001055194c046dd91ab750 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 15:20:59 +0000 Subject: [PATCH 40/72] Finish adding the extensional variants --- src/Std/Data/DHashMap/DecidableEq.lean | 2 +- src/Std/Data/ExtDHashMap/DecidableEq.lean | 3 +-- src/Std/Data/ExtHashMap.lean | 1 + src/Std/Data/ExtHashMap/DecidableEq.lean | 28 +++++++++++++++++++++++ src/Std/Data/ExtHashSet.lean | 1 + src/Std/Data/ExtHashSet/DecidableEq.lean | 28 +++++++++++++++++++++++ 6 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 src/Std/Data/ExtHashMap/DecidableEq.lean create mode 100644 src/Std/Data/ExtHashSet/DecidableEq.lean diff --git a/src/Std/Data/DHashMap/DecidableEq.lean b/src/Std/Data/DHashMap/DecidableEq.lean index eb0dad4de37c..1ac10482d3f2 100644 --- a/src/Std/Data/DHashMap/DecidableEq.lean +++ b/src/Std/Data/DHashMap/DecidableEq.lean @@ -1,5 +1,5 @@ /- -Copyright (c) 2024 Lean FRO, LLC. All rights reserved. +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Wojciech Różowski -/ diff --git a/src/Std/Data/ExtDHashMap/DecidableEq.lean b/src/Std/Data/ExtDHashMap/DecidableEq.lean index 3c88fa8fbfc1..346c2c682879 100644 --- a/src/Std/Data/ExtDHashMap/DecidableEq.lean +++ b/src/Std/Data/ExtDHashMap/DecidableEq.lean @@ -1,5 +1,5 @@ /- -Copyright (c) 2024 Lean FRO, LLC. All rights reserved. +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Wojciech Różowski -/ @@ -23,5 +23,4 @@ open scoped Std.DHashMap instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] : DecidableEq (ExtDHashMap α β) := fun m₁ m₂ => @decidable_of_decidable_of_iff (m₁ == m₂) _ _ ⟨by apply ExtDHashMap.eq_of_beq_true, by apply ExtDHashMap.beq_of_eq⟩ - end Std.ExtDHashMap diff --git a/src/Std/Data/ExtHashMap.lean b/src/Std/Data/ExtHashMap.lean index 34110e1cf683..23d51a20157b 100644 --- a/src/Std/Data/ExtHashMap.lean +++ b/src/Std/Data/ExtHashMap.lean @@ -8,3 +8,4 @@ module prelude public import Std.Data.ExtHashMap.Basic public import Std.Data.ExtHashMap.Lemmas +public import Std.Data.ExtHashMap.DecidableEq diff --git a/src/Std/Data/ExtHashMap/DecidableEq.lean b/src/Std/Data/ExtHashMap/DecidableEq.lean new file mode 100644 index 000000000000..e9ea9ef6fa66 --- /dev/null +++ b/src/Std/Data/ExtHashMap/DecidableEq.lean @@ -0,0 +1,28 @@ +/- +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wojciech Różowski +-/ +module + +prelude +public import Std.Data.ExtDHashMap.Basic +public import Std.Data.ExtHashMap.Basic +public import Std.Data.ExtHashMap.Lemmas +public import Std.Data.DHashMap.DecidableEq + +public section + +/-! +# Decidable equality for `ExtHashMap` +-/ + +namespace Std.ExtHashMap + +open scoped Std.DHashMap + +instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] : DecidableEq (ExtHashMap α β) := + fun ⟨m₁⟩ ⟨m₂⟩ => @decidable_of_decidable_of_iff (ExtDHashMap.Const.beq m₁ m₂) _ _ + (by rw [mk.injEq]; exact ⟨by apply ExtDHashMap.Const.eq_of_beq_eq_true, by apply ExtDHashMap.Const.beq_of_eq⟩) + +end Std.ExtHashMap diff --git a/src/Std/Data/ExtHashSet.lean b/src/Std/Data/ExtHashSet.lean index eaede3f865c4..5ae20f2cad3a 100644 --- a/src/Std/Data/ExtHashSet.lean +++ b/src/Std/Data/ExtHashSet.lean @@ -8,3 +8,4 @@ module prelude public import Std.Data.ExtHashSet.Basic public import Std.Data.ExtHashSet.Lemmas +public import Std.Data.ExtHashSet.DecidableEq diff --git a/src/Std/Data/ExtHashSet/DecidableEq.lean b/src/Std/Data/ExtHashSet/DecidableEq.lean new file mode 100644 index 000000000000..7523797713ea --- /dev/null +++ b/src/Std/Data/ExtHashSet/DecidableEq.lean @@ -0,0 +1,28 @@ +/- +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wojciech Różowski +-/ +module + +prelude +public import Std.Data.ExtDHashMap.Basic +public import Std.Data.ExtHashSet.Basic +public import Std.Data.ExtHashSet.Lemmas +public import Std.Data.DHashMap.DecidableEq + +public section + +/-! +# Decidable equality for `ExtHashSet` +-/ + +namespace Std.ExtHashSet + +open scoped Std.ExtDHashMap + +instance {α : Type u} [DecidableEq α] [Hashable α] : DecidableEq (ExtHashSet α) := + fun ⟨⟨m₁⟩⟩ ⟨⟨m₂⟩⟩ => @decidable_of_decidable_of_iff (ExtDHashMap.Const.beq_unit m₁ m₂) _ _ + (by rw [mk.injEq, ExtHashMap.mk.injEq]; exact ⟨by apply ExtDHashMap.Const.eq_of_beq_unit_eq_true, by apply ExtDHashMap.Const.beq_unit_of_eq⟩) + +end Std.ExtHashSet From 84b1bd75b9c8daea65e95b417b935ce560893ede Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 15:33:37 +0000 Subject: [PATCH 41/72] Try refactoring `ExtDHashMap` --- src/Std/Data/ExtDHashMap/Basic.lean | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index 0c4279f9d783..a0bc1366904f 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -368,25 +368,20 @@ def beq [LawfulBEq α] [∀ k, BEq (β k)] (m₁ m₂ : ExtDHashMap α β) : Boo instance [LawfulBEq α] [∀ k, BEq (β k)] : BEq (ExtDHashMap α β) := ⟨beq⟩ -theorem beq_of_eq [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] (m₁ m₂ : ExtDHashMap α β) (hyp : m₁ = m₂) : m₁ == m₂ := by - induction m₁ - case mk a => - induction m₂ - case mk b => - exact DHashMap.Equiv.beq <| exact hyp - -theorem eq_of_beq_true [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] (m₁ m₂ : ExtDHashMap α β) (hyp : (m₁ == m₂) = true) : m₁ = m₂ := by - induction m₁ - case mk a => - induction m₂ - case mk b => - apply sound <| DHashMap.equiv_of_beq hyp - instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : ReflBEq (ExtDHashMap α β) where - rfl {a} := by apply beq_of_eq; rfl + rfl {a} := by + induction a + case mk a => + apply DHashMap.Equiv.beq + · apply DHashMap.Equiv.refl instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : LawfulBEq (ExtDHashMap α β) where - eq_of_beq := fun hyp => eq_of_beq_true _ _ hyp + eq_of_beq {m₁} {m₂} hyp := by + induction m₁ + case mk a => + induction m₂ + case mk b => + apply sound <| DHashMap.equiv_of_beq hyp namespace Const From 9ef08437e88f5ffb453f9c019a2427051a2bddb7 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 16:43:44 +0000 Subject: [PATCH 42/72] Put the code I have so far --- src/Std/Data/DHashMap/Raw.lean | 3 +++ src/Std/Data/DHashMap/RawDecidableEq.lean | 25 +++++++++++++++++++++++ src/Std/Data/ExtDHashMap/DecidableEq.lean | 2 +- src/Std/Data/HashMap/RawDecidableEq.lean | 25 +++++++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/Std/Data/DHashMap/RawDecidableEq.lean create mode 100644 src/Std/Data/HashMap/RawDecidableEq.lean diff --git a/src/Std/Data/DHashMap/Raw.lean b/src/Std/Data/DHashMap/Raw.lean index e9fac297b12e..9ad639f37aba 100644 --- a/src/Std/Data/DHashMap/Raw.lean +++ b/src/Std/Data/DHashMap/Raw.lean @@ -845,6 +845,9 @@ theorem WF.diff [BEq α] [Hashable α] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) end WF +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := + @Std.DHashMap.Internal.Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ + end Raw end DHashMap diff --git a/src/Std/Data/DHashMap/RawDecidableEq.lean b/src/Std/Data/DHashMap/RawDecidableEq.lean new file mode 100644 index 000000000000..68b8460a3d36 --- /dev/null +++ b/src/Std/Data/DHashMap/RawDecidableEq.lean @@ -0,0 +1,25 @@ +/- +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wojciech Różowski +-/ +module + +prelude +public import Std.Data.DHashMap.Internal.RawLemmas +import all Std.Data.DHashMap.Raw + +public section + +/-! +# Decidable equivalence for `DHashMap.Raw` +-/ + +open Std.DHashMap.Internal + +namespace Std.DHashMap + +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := + @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ + +end Std.DHashMap diff --git a/src/Std/Data/ExtDHashMap/DecidableEq.lean b/src/Std/Data/ExtDHashMap/DecidableEq.lean index 346c2c682879..d45f95954d24 100644 --- a/src/Std/Data/ExtDHashMap/DecidableEq.lean +++ b/src/Std/Data/ExtDHashMap/DecidableEq.lean @@ -21,6 +21,6 @@ namespace Std.ExtDHashMap open scoped Std.DHashMap instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] : DecidableEq (ExtDHashMap α β) := - fun m₁ m₂ => @decidable_of_decidable_of_iff (m₁ == m₂) _ _ ⟨by apply ExtDHashMap.eq_of_beq_true, by apply ExtDHashMap.beq_of_eq⟩ + fun m₁ m₂ => @decidable_of_decidable_of_iff (m₁ == m₂) _ _ ⟨by simp, by simp⟩ end Std.ExtDHashMap diff --git a/src/Std/Data/HashMap/RawDecidableEq.lean b/src/Std/Data/HashMap/RawDecidableEq.lean new file mode 100644 index 000000000000..fc24dd51f605 --- /dev/null +++ b/src/Std/Data/HashMap/RawDecidableEq.lean @@ -0,0 +1,25 @@ +/- +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wojciech Różowski +-/ +module + +prelude +public import Std.Data.HashMap.RawLemmas +import all Std.Data.HashMap.Raw + +public section + +/-! +# Decidable equivalence for `DHashMap.Raw` +-/ + +open Std.DHashMap.Internal + +namespace Std.HashMap + +instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := by + apply @decidable_of_iff (m₁.Equiv m₂) (m₁.inner.Equiv m₂.inner) (by exact ⟨fun h => ⟨h⟩, fun h => h.1⟩) <| @Raw₀.Equiv.decide α (fun _ => β) _ _ _ ⟨m₁.inner, h₁.out.size_buckets_pos⟩ ⟨m₂.inner, h₂.out.size_buckets_pos⟩ h₁.out h₂.out + +end Std.HashMap From efdb7ab8e49169e2464054ab2347629d67903e3f Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 16:44:40 +0000 Subject: [PATCH 43/72] Forgotten instance --- src/Std/Data/DHashMap/Raw.lean | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Std/Data/DHashMap/Raw.lean b/src/Std/Data/DHashMap/Raw.lean index 9ad639f37aba..e9fac297b12e 100644 --- a/src/Std/Data/DHashMap/Raw.lean +++ b/src/Std/Data/DHashMap/Raw.lean @@ -845,9 +845,6 @@ theorem WF.diff [BEq α] [Hashable α] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) end WF -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - @Std.DHashMap.Internal.Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ - end Raw end DHashMap From 55b3d02c44d870f94e96746114cc3e0f453b1214 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 17:19:54 +0000 Subject: [PATCH 44/72] Refactor --- src/Std/Data/DHashMap.lean | 1 - src/Std/Data/DHashMap/DecidableEq.lean | 27 ---------------------- src/Std/Data/DHashMap/Lemmas.lean | 4 ++++ src/Std/Data/DHashMap/RawDecidableEq.lean | 25 -------------------- src/Std/Data/DHashMap/RawLemmas.lean | 3 +++ src/Std/Data/ExtDHashMap.lean | 1 - src/Std/Data/ExtDHashMap/Basic.lean | 3 +++ src/Std/Data/ExtDHashMap/DecidableEq.lean | 26 --------------------- src/Std/Data/ExtHashMap.lean | 1 - src/Std/Data/ExtHashMap/Basic.lean | 3 +++ src/Std/Data/ExtHashMap/DecidableEq.lean | 28 ----------------------- src/Std/Data/ExtHashSet.lean | 1 - src/Std/Data/ExtHashSet/Basic.lean | 3 +++ src/Std/Data/ExtHashSet/DecidableEq.lean | 28 ----------------------- src/Std/Data/HashMap/Lemmas.lean | 4 ++++ src/Std/Data/HashMap/RawDecidableEq.lean | 25 -------------------- src/Std/Data/HashMap/RawLemmas.lean | 4 ++++ src/Std/Data/HashSet/Lemmas.lean | 4 ++++ src/Std/Data/HashSet/RawLemmas.lean | 3 +++ 19 files changed, 31 insertions(+), 163 deletions(-) delete mode 100644 src/Std/Data/DHashMap/DecidableEq.lean delete mode 100644 src/Std/Data/DHashMap/RawDecidableEq.lean delete mode 100644 src/Std/Data/ExtDHashMap/DecidableEq.lean delete mode 100644 src/Std/Data/ExtHashMap/DecidableEq.lean delete mode 100644 src/Std/Data/ExtHashSet/DecidableEq.lean delete mode 100644 src/Std/Data/HashMap/RawDecidableEq.lean diff --git a/src/Std/Data/DHashMap.lean b/src/Std/Data/DHashMap.lean index 64f53f3dfe8e..03860f758875 100644 --- a/src/Std/Data/DHashMap.lean +++ b/src/Std/Data/DHashMap.lean @@ -11,4 +11,3 @@ public import Std.Data.DHashMap.AdditionalOperations public import Std.Data.DHashMap.Iterator public import Std.Data.DHashMap.Lemmas public import Std.Data.DHashMap.IteratorLemmas -public import Std.Data.DHashMap.DecidableEq diff --git a/src/Std/Data/DHashMap/DecidableEq.lean b/src/Std/Data/DHashMap/DecidableEq.lean deleted file mode 100644 index 1ac10482d3f2..000000000000 --- a/src/Std/Data/DHashMap/DecidableEq.lean +++ /dev/null @@ -1,27 +0,0 @@ -/- -Copyright (c) 2025 Lean FRO, LLC. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Wojciech Różowski --/ -module - -prelude -public import Std.Data.DHashMap.Internal.RawLemmas -import all Std.Data.DHashMap.Basic -public import Std.Data.DHashMap.AdditionalOperations -import all Std.Data.DHashMap.AdditionalOperations - -public section - -/-! -# Decidable equivalence for `DHashMap` --/ - -open Std.DHashMap.Internal - -namespace Std.DHashMap - -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| - @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 - -end Std.DHashMap diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index 2597749d8703..02774ff174aa 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -5345,5 +5345,9 @@ theorem toList_map {m : DHashMap α fun _ => β} end Const end map + +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| + @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 + attribute [simp] contains_eq_false_iff_not_mem end Std.DHashMap diff --git a/src/Std/Data/DHashMap/RawDecidableEq.lean b/src/Std/Data/DHashMap/RawDecidableEq.lean deleted file mode 100644 index 68b8460a3d36..000000000000 --- a/src/Std/Data/DHashMap/RawDecidableEq.lean +++ /dev/null @@ -1,25 +0,0 @@ -/- -Copyright (c) 2025 Lean FRO, LLC. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Wojciech Różowski --/ -module - -prelude -public import Std.Data.DHashMap.Internal.RawLemmas -import all Std.Data.DHashMap.Raw - -public section - -/-! -# Decidable equivalence for `DHashMap.Raw` --/ - -open Std.DHashMap.Internal - -namespace Std.DHashMap - -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ - -end Std.DHashMap diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index 920a14123836..329b476ae789 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -6030,6 +6030,9 @@ end Const end map +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := + @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ + attribute [simp] contains_eq_false_iff_not_mem end Raw end Std.DHashMap diff --git a/src/Std/Data/ExtDHashMap.lean b/src/Std/Data/ExtDHashMap.lean index e0044d193d8a..2830bb050c79 100644 --- a/src/Std/Data/ExtDHashMap.lean +++ b/src/Std/Data/ExtDHashMap.lean @@ -8,4 +8,3 @@ module prelude public import Std.Data.ExtDHashMap.Basic public import Std.Data.ExtDHashMap.Lemmas -public import Std.Data.ExtDHashMap.DecidableEq diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index a0bc1366904f..5c83e852e559 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -383,6 +383,9 @@ instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : LawfulBE case mk b => apply sound <| DHashMap.equiv_of_beq hyp +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] : DecidableEq (ExtDHashMap α β) := + fun m₁ m₂ => @decidable_of_decidable_of_iff (m₁ == m₂) _ _ ⟨by simp, by simp⟩ + namespace Const variable {β : Type v} diff --git a/src/Std/Data/ExtDHashMap/DecidableEq.lean b/src/Std/Data/ExtDHashMap/DecidableEq.lean deleted file mode 100644 index d45f95954d24..000000000000 --- a/src/Std/Data/ExtDHashMap/DecidableEq.lean +++ /dev/null @@ -1,26 +0,0 @@ -/- -Copyright (c) 2025 Lean FRO, LLC. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Wojciech Różowski --/ -module - -prelude -public import Std.Data.ExtDHashMap.Basic -public import Std.Data.ExtDHashMap.Lemmas -public import Std.Data.DHashMap.DecidableEq - -public section - -/-! -# Decidable equality for `ExtDHashMap` --/ - -namespace Std.ExtDHashMap - -open scoped Std.DHashMap - -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] : DecidableEq (ExtDHashMap α β) := - fun m₁ m₂ => @decidable_of_decidable_of_iff (m₁ == m₂) _ _ ⟨by simp, by simp⟩ - -end Std.ExtDHashMap diff --git a/src/Std/Data/ExtHashMap.lean b/src/Std/Data/ExtHashMap.lean index 23d51a20157b..34110e1cf683 100644 --- a/src/Std/Data/ExtHashMap.lean +++ b/src/Std/Data/ExtHashMap.lean @@ -8,4 +8,3 @@ module prelude public import Std.Data.ExtHashMap.Basic public import Std.Data.ExtHashMap.Lemmas -public import Std.Data.ExtHashMap.DecidableEq diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index 95a0f9c8a6c4..287037b45ccf 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -268,6 +268,9 @@ instance [LawfulBEq α] [BEq β] [LawfulBEq β] : LawfulBEq (ExtHashMap α β) w apply ExtDHashMap.Const.eq_of_beq_eq_true exact hyp +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] : DecidableEq (ExtDHashMap α β) := + fun m₁ m₂ => @decidable_of_decidable_of_iff (m₁ == m₂) _ _ ⟨by simp, by simp⟩ + @[inline, inherit_doc ExtDHashMap.inter] def inter [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashMap α β) : ExtHashMap α β := ⟨ExtDHashMap.inter m₁.inner m₂.inner⟩ diff --git a/src/Std/Data/ExtHashMap/DecidableEq.lean b/src/Std/Data/ExtHashMap/DecidableEq.lean deleted file mode 100644 index e9ea9ef6fa66..000000000000 --- a/src/Std/Data/ExtHashMap/DecidableEq.lean +++ /dev/null @@ -1,28 +0,0 @@ -/- -Copyright (c) 2025 Lean FRO, LLC. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Wojciech Różowski --/ -module - -prelude -public import Std.Data.ExtDHashMap.Basic -public import Std.Data.ExtHashMap.Basic -public import Std.Data.ExtHashMap.Lemmas -public import Std.Data.DHashMap.DecidableEq - -public section - -/-! -# Decidable equality for `ExtHashMap` --/ - -namespace Std.ExtHashMap - -open scoped Std.DHashMap - -instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] : DecidableEq (ExtHashMap α β) := - fun ⟨m₁⟩ ⟨m₂⟩ => @decidable_of_decidable_of_iff (ExtDHashMap.Const.beq m₁ m₂) _ _ - (by rw [mk.injEq]; exact ⟨by apply ExtDHashMap.Const.eq_of_beq_eq_true, by apply ExtDHashMap.Const.beq_of_eq⟩) - -end Std.ExtHashMap diff --git a/src/Std/Data/ExtHashSet.lean b/src/Std/Data/ExtHashSet.lean index 5ae20f2cad3a..eaede3f865c4 100644 --- a/src/Std/Data/ExtHashSet.lean +++ b/src/Std/Data/ExtHashSet.lean @@ -8,4 +8,3 @@ module prelude public import Std.Data.ExtHashSet.Basic public import Std.Data.ExtHashSet.Lemmas -public import Std.Data.ExtHashSet.DecidableEq diff --git a/src/Std/Data/ExtHashSet/Basic.lean b/src/Std/Data/ExtHashSet/Basic.lean index 932a10003566..531463553795 100644 --- a/src/Std/Data/ExtHashSet/Basic.lean +++ b/src/Std/Data/ExtHashSet/Basic.lean @@ -233,6 +233,9 @@ instance [LawfulBEq α] : LawfulBEq (ExtHashSet α) where apply ExtDHashMap.Const.eq_of_beq_unit_eq_true · exact hyp +instance {α : Type u} [DecidableEq α] [Hashable α] : DecidableEq (ExtHashSet α) := + fun m₁ m₂ => @decidable_of_decidable_of_iff (m₁ == m₂) _ _ ⟨by simp, by simp⟩ + /-- Computes the intersection of the given hash sets. diff --git a/src/Std/Data/ExtHashSet/DecidableEq.lean b/src/Std/Data/ExtHashSet/DecidableEq.lean deleted file mode 100644 index 7523797713ea..000000000000 --- a/src/Std/Data/ExtHashSet/DecidableEq.lean +++ /dev/null @@ -1,28 +0,0 @@ -/- -Copyright (c) 2025 Lean FRO, LLC. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Wojciech Różowski --/ -module - -prelude -public import Std.Data.ExtDHashMap.Basic -public import Std.Data.ExtHashSet.Basic -public import Std.Data.ExtHashSet.Lemmas -public import Std.Data.DHashMap.DecidableEq - -public section - -/-! -# Decidable equality for `ExtHashSet` --/ - -namespace Std.ExtHashSet - -open scoped Std.ExtDHashMap - -instance {α : Type u} [DecidableEq α] [Hashable α] : DecidableEq (ExtHashSet α) := - fun ⟨⟨m₁⟩⟩ ⟨⟨m₂⟩⟩ => @decidable_of_decidable_of_iff (ExtDHashMap.Const.beq_unit m₁ m₂) _ _ - (by rw [mk.injEq, ExtHashMap.mk.injEq]; exact ⟨by apply ExtDHashMap.Const.eq_of_beq_unit_eq_true, by apply ExtDHashMap.Const.beq_unit_of_eq⟩) - -end Std.ExtHashSet diff --git a/src/Std/Data/HashMap/Lemmas.lean b/src/Std/Data/HashMap/Lemmas.lean index 423b6469f48c..0ba09087347a 100644 --- a/src/Std/Data/HashMap/Lemmas.lean +++ b/src/Std/Data/HashMap/Lemmas.lean @@ -3492,5 +3492,9 @@ theorem getKeyD_map [EquivBEq α] [LawfulHashable α] DHashMap.getKeyD_map end map + +instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] (m₁ m₂ : HashMap α β) : Decidable (m₁ ~m m₂) := + @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| DHashMap.instDecidableEquivOfDecidableEq m₁.inner m₂.inner + attribute [simp] contains_eq_false_iff_not_mem end Std.HashMap diff --git a/src/Std/Data/HashMap/RawDecidableEq.lean b/src/Std/Data/HashMap/RawDecidableEq.lean deleted file mode 100644 index fc24dd51f605..000000000000 --- a/src/Std/Data/HashMap/RawDecidableEq.lean +++ /dev/null @@ -1,25 +0,0 @@ -/- -Copyright (c) 2025 Lean FRO, LLC. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Wojciech Różowski --/ -module - -prelude -public import Std.Data.HashMap.RawLemmas -import all Std.Data.HashMap.Raw - -public section - -/-! -# Decidable equivalence for `DHashMap.Raw` --/ - -open Std.DHashMap.Internal - -namespace Std.HashMap - -instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := by - apply @decidable_of_iff (m₁.Equiv m₂) (m₁.inner.Equiv m₂.inner) (by exact ⟨fun h => ⟨h⟩, fun h => h.1⟩) <| @Raw₀.Equiv.decide α (fun _ => β) _ _ _ ⟨m₁.inner, h₁.out.size_buckets_pos⟩ ⟨m₂.inner, h₂.out.size_buckets_pos⟩ h₁.out h₂.out - -end Std.HashMap diff --git a/src/Std/Data/HashMap/RawLemmas.lean b/src/Std/Data/HashMap/RawLemmas.lean index f5da73d93d82..1e910ffd8abd 100644 --- a/src/Std/Data/HashMap/RawLemmas.lean +++ b/src/Std/Data/HashMap/RawLemmas.lean @@ -3553,6 +3553,10 @@ theorem getD_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] DHashMap.Raw.Const.getD_map_of_getKey?_eq_some h.out h' end map + +instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := + @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| DHashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out + attribute [simp] contains_eq_false_iff_not_mem end Raw diff --git a/src/Std/Data/HashSet/Lemmas.lean b/src/Std/Data/HashSet/Lemmas.lean index f54aa8f59ee1..c2320da1dcd6 100644 --- a/src/Std/Data/HashSet/Lemmas.lean +++ b/src/Std/Data/HashSet/Lemmas.lean @@ -1535,5 +1535,9 @@ theorem getD_filter [EquivBEq α] [LawfulHashable α] HashMap.getKeyD_filter_key end filter + +instance {α : Type u} [DecidableEq α] [Hashable α] (m₁ m₂ : HashSet α) : Decidable (m₁ ~m m₂) := + @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| HashMap.instDecidableEquivOfDecidableEq m₁.inner m₂.inner + attribute [simp] contains_eq_false_iff_not_mem end Std.HashSet diff --git a/src/Std/Data/HashSet/RawLemmas.lean b/src/Std/Data/HashSet/RawLemmas.lean index f8d8742300fc..beff0f35ced2 100644 --- a/src/Std/Data/HashSet/RawLemmas.lean +++ b/src/Std/Data/HashSet/RawLemmas.lean @@ -1607,6 +1607,9 @@ theorem get_filter [EquivBEq α] [LawfulHashable α] end filter +instance {α : Type u} [DecidableEq α] [Hashable α] {m₁ m₂ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := + @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| HashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out + attribute [simp] contains_eq_false_iff_not_mem end Raw From 1a93a9f70166674a88ffb7270d999294734441a4 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 18:26:23 +0000 Subject: [PATCH 45/72] cleanup extensional variants --- src/Std/Data/ExtHashMap/Basic.lean | 14 +++++--------- src/Std/Data/ExtHashSet/Basic.lean | 19 +++++-------------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index 95a0f9c8a6c4..ac95d3205626 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -258,15 +258,11 @@ instance [LawfulBEq α] [BEq β] [ReflBEq β] : ReflBEq (ExtHashMap α β) where rfl := by intro a; apply ExtDHashMap.Const.beq_of_eq; rfl instance [LawfulBEq α] [BEq β] [LawfulBEq β] : LawfulBEq (ExtHashMap α β) where - eq_of_beq := by - intro a b hyp - cases a - case mk a₀ => - cases b - case mk b₀ => - simp only [mk.injEq] - apply ExtDHashMap.Const.eq_of_beq_eq_true - exact hyp + eq_of_beq {a} {b} hyp := by + have ⟨a⟩ := a + have ⟨b⟩ := b + simp only [mk.injEq] at |- hyp + exact ExtDHashMap.Const.eq_of_beq_eq_true _ _ hyp @[inline, inherit_doc ExtDHashMap.inter] def inter [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashMap α β) : ExtHashMap α β := ⟨ExtDHashMap.inter m₁.inner m₂.inner⟩ diff --git a/src/Std/Data/ExtHashSet/Basic.lean b/src/Std/Data/ExtHashSet/Basic.lean index 932a10003566..221f7c6c8ca1 100644 --- a/src/Std/Data/ExtHashSet/Basic.lean +++ b/src/Std/Data/ExtHashSet/Basic.lean @@ -218,20 +218,11 @@ instance [LawfulBEq α] : ReflBEq (ExtHashSet α) where rfl instance [LawfulBEq α] : LawfulBEq (ExtHashSet α) where - eq_of_beq := by - intro a b hyp - cases a - case mk a₀ => - cases b - case mk b₀ => - cases a₀ - case mk a₁ => - cases b₀ - case mk b₁ => - simp only [mk.injEq, ExtHashMap.mk.injEq] - simp only [BEq.beq, beq] at hyp - apply ExtDHashMap.Const.eq_of_beq_unit_eq_true - · exact hyp + eq_of_beq {a} {b} hyp := by + have ⟨⟨a⟩⟩ := a + have ⟨⟨b⟩⟩ := b + simp only [mk.injEq, ExtHashMap.mk.injEq] at |- hyp + exact ExtDHashMap.Const.eq_of_beq_unit_eq_true _ _ hyp /-- Computes the intersection of the given hash sets. From 4e012a6db1103023eda3d81f08fa6d82825207ca Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Tue, 2 Dec 2025 19:06:57 +0000 Subject: [PATCH 46/72] further renaming --- src/Std/Data/ExtDHashMap/Basic.lean | 6 +++--- src/Std/Data/ExtHashMap/Basic.lean | 2 +- src/Std/Data/ExtHashSet/Basic.lean | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index a0bc1366904f..0ae70093fe23 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -397,7 +397,7 @@ theorem beq_of_eq [LawfulBEq α] [BEq β] [ReflBEq β] (m₁ m₂ : ExtDHashMap case mk b => exact DHashMap.Const.Equiv.beq <| exact h -theorem eq_of_beq_eq_true [LawfulBEq α] [BEq β] [LawfulBEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) (h : Const.beq m₁ m₂) : m₁ = m₂ := by +theorem eq_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) (h : Const.beq m₁ m₂) : m₁ = m₂ := by induction m₁ case mk a => induction m₂ @@ -416,8 +416,8 @@ theorem beq_unit_of_eq [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) apply beq_of_eq exact h -theorem eq_of_beq_unit_eq_true [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : Const.beq_unit m₁ m₂) : m₁ = m₂ := by - apply eq_of_beq_eq_true +theorem eq_of_beq_unit [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : Const.beq_unit m₁ m₂) : m₁ = m₂ := by + apply eq_of_beq exact h end Const diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index ac95d3205626..8c2e668a2cca 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -262,7 +262,7 @@ instance [LawfulBEq α] [BEq β] [LawfulBEq β] : LawfulBEq (ExtHashMap α β) w have ⟨a⟩ := a have ⟨b⟩ := b simp only [mk.injEq] at |- hyp - exact ExtDHashMap.Const.eq_of_beq_eq_true _ _ hyp + exact ExtDHashMap.Const.eq_of_beq _ _ hyp @[inline, inherit_doc ExtDHashMap.inter] def inter [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashMap α β) : ExtHashMap α β := ⟨ExtDHashMap.inter m₁.inner m₂.inner⟩ diff --git a/src/Std/Data/ExtHashSet/Basic.lean b/src/Std/Data/ExtHashSet/Basic.lean index 221f7c6c8ca1..6609ba6e813b 100644 --- a/src/Std/Data/ExtHashSet/Basic.lean +++ b/src/Std/Data/ExtHashSet/Basic.lean @@ -222,7 +222,7 @@ instance [LawfulBEq α] : LawfulBEq (ExtHashSet α) where have ⟨⟨a⟩⟩ := a have ⟨⟨b⟩⟩ := b simp only [mk.injEq, ExtHashMap.mk.injEq] at |- hyp - exact ExtDHashMap.Const.eq_of_beq_unit_eq_true _ _ hyp + exact ExtDHashMap.Const.eq_of_beq_unit _ _ hyp /-- Computes the intersection of the given hash sets. From befc92b8cf87b97c63f6c09b62e974b1b0e8570d Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 3 Dec 2025 12:13:53 +0000 Subject: [PATCH 47/72] Refactor Decidable Equiv --- src/Std/Data.lean | 3 +++ src/Std/Data/DHashMap.lean | 1 + src/Std/Data/DHashMap/DecidableEquiv.lean | 24 ++++++++++++++++++++ src/Std/Data/DHashMap/Lemmas.lean | 3 --- src/Std/Data/DHashMap/RawDecidableEquiv.lean | 24 ++++++++++++++++++++ src/Std/Data/DHashMap/RawLemmas.lean | 3 --- src/Std/Data/HashMap.lean | 1 + src/Std/Data/HashMap/DecidableEquiv.lean | 23 +++++++++++++++++++ src/Std/Data/HashMap/Lemmas.lean | 3 --- src/Std/Data/HashMap/RawDecidableEquiv.lean | 23 +++++++++++++++++++ src/Std/Data/HashMap/RawLemmas.lean | 3 --- src/Std/Data/HashSet.lean | 1 + src/Std/Data/HashSet/DecidableEquiv.lean | 23 +++++++++++++++++++ src/Std/Data/HashSet/Lemmas.lean | 3 --- src/Std/Data/HashSet/RawDecidableEquiv.lean | 23 +++++++++++++++++++ src/Std/Data/HashSet/RawLemmas.lean | 3 --- 16 files changed, 146 insertions(+), 18 deletions(-) create mode 100644 src/Std/Data/DHashMap/DecidableEquiv.lean create mode 100644 src/Std/Data/DHashMap/RawDecidableEquiv.lean create mode 100644 src/Std/Data/HashMap/DecidableEquiv.lean create mode 100644 src/Std/Data/HashMap/RawDecidableEquiv.lean create mode 100644 src/Std/Data/HashSet/DecidableEquiv.lean create mode 100644 src/Std/Data/HashSet/RawDecidableEquiv.lean diff --git a/src/Std/Data.lean b/src/Std/Data.lean index 0479b505e7d3..9978bf2a998e 100644 --- a/src/Std/Data.lean +++ b/src/Std/Data.lean @@ -23,8 +23,11 @@ public import Std.Data.ExtTreeSet -- the well-formedness invariant, so we need to additionally import the files that deal with the -- unbundled version public import Std.Data.DHashMap.RawLemmas +public import Std.Data.DHashMap.DecidableEquiv public import Std.Data.HashMap.RawLemmas +public import Std.Data.HashMap.DecidableEquiv public import Std.Data.HashSet.RawLemmas +public import Std.Data.HashSet.DecidableEquiv public import Std.Data.DTreeMap.Raw public import Std.Data.TreeMap.Raw public import Std.Data.TreeSet.Raw diff --git a/src/Std/Data/DHashMap.lean b/src/Std/Data/DHashMap.lean index 03860f758875..a25cddf7ddf6 100644 --- a/src/Std/Data/DHashMap.lean +++ b/src/Std/Data/DHashMap.lean @@ -11,3 +11,4 @@ public import Std.Data.DHashMap.AdditionalOperations public import Std.Data.DHashMap.Iterator public import Std.Data.DHashMap.Lemmas public import Std.Data.DHashMap.IteratorLemmas +public import Std.Data.DHashMap.DecidableEquiv diff --git a/src/Std/Data/DHashMap/DecidableEquiv.lean b/src/Std/Data/DHashMap/DecidableEquiv.lean new file mode 100644 index 000000000000..13baaa636282 --- /dev/null +++ b/src/Std/Data/DHashMap/DecidableEquiv.lean @@ -0,0 +1,24 @@ +/- +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wojciech Różowski +-/ +module + +prelude +public import Std.Data.DHashMap.Internal.RawLemmas + +public section + +/-! +# Decidable equivalence for `DHashMap` +-/ + +open Std.DHashMap.Internal + +namespace Std.DHashMap + +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| + @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 + +end Std.DHashMap diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index 02774ff174aa..49f2e18fe5f4 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -5346,8 +5346,5 @@ end Const end map -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| - @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 - attribute [simp] contains_eq_false_iff_not_mem end Std.DHashMap diff --git a/src/Std/Data/DHashMap/RawDecidableEquiv.lean b/src/Std/Data/DHashMap/RawDecidableEquiv.lean new file mode 100644 index 000000000000..b603779d8a86 --- /dev/null +++ b/src/Std/Data/DHashMap/RawDecidableEquiv.lean @@ -0,0 +1,24 @@ +/- +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wojciech Różowski +-/ +module + +prelude +public import Std.Data.DHashMap.Internal.RawLemmas + +public section + +/-! +# Decidable equivalence for `DHashMap.Raw` +-/ + +open Std.DHashMap.Internal + +namespace Std.DHashMap.Raw + +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := + @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ + +end Std.DHashMap.Raw diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index 329b476ae789..920a14123836 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -6030,9 +6030,6 @@ end Const end map -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ - attribute [simp] contains_eq_false_iff_not_mem end Raw end Std.DHashMap diff --git a/src/Std/Data/HashMap.lean b/src/Std/Data/HashMap.lean index 02b56e2ec617..04e3a2086bec 100644 --- a/src/Std/Data/HashMap.lean +++ b/src/Std/Data/HashMap.lean @@ -11,3 +11,4 @@ public import Std.Data.HashMap.AdditionalOperations public import Std.Data.HashMap.Iterator public import Std.Data.HashMap.Lemmas public import Std.Data.HashMap.IteratorLemmas +public import Std.Data.HashMap.DecidableEquiv diff --git a/src/Std/Data/HashMap/DecidableEquiv.lean b/src/Std/Data/HashMap/DecidableEquiv.lean new file mode 100644 index 000000000000..f6107eaed75c --- /dev/null +++ b/src/Std/Data/HashMap/DecidableEquiv.lean @@ -0,0 +1,23 @@ +/- +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wojciech Różowski +-/ +module + +prelude +public import Std.Data.DHashMap.DecidableEquiv +public import Std.Data.HashMap.Basic + +public section + +/-! +# Decidable equivalence for `HashMap` +-/ + +namespace Std.HashMap + +instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] (m₁ m₂ : HashMap α β) : Decidable (m₁ ~m m₂) := + @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| DHashMap.instDecidableEquivOfDecidableEq m₁.inner m₂.inner + +end Std.HashMap diff --git a/src/Std/Data/HashMap/Lemmas.lean b/src/Std/Data/HashMap/Lemmas.lean index 0ba09087347a..cc48d96dd887 100644 --- a/src/Std/Data/HashMap/Lemmas.lean +++ b/src/Std/Data/HashMap/Lemmas.lean @@ -3493,8 +3493,5 @@ theorem getKeyD_map [EquivBEq α] [LawfulHashable α] end map -instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] (m₁ m₂ : HashMap α β) : Decidable (m₁ ~m m₂) := - @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| DHashMap.instDecidableEquivOfDecidableEq m₁.inner m₂.inner - attribute [simp] contains_eq_false_iff_not_mem end Std.HashMap diff --git a/src/Std/Data/HashMap/RawDecidableEquiv.lean b/src/Std/Data/HashMap/RawDecidableEquiv.lean new file mode 100644 index 000000000000..9537406810d7 --- /dev/null +++ b/src/Std/Data/HashMap/RawDecidableEquiv.lean @@ -0,0 +1,23 @@ +/- +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wojciech Różowski +-/ +module + +prelude +public import Std.Data.DHashMap.RawDecidableEquiv +public import Std.Data.HashMap.Raw + +public section + +/-! +# Decidable equivalence for `HashMap.Raw` +-/ + +namespace Std.HashMap.Raw + +instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := + @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| DHashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out + +end Std.HashMap.Raw diff --git a/src/Std/Data/HashMap/RawLemmas.lean b/src/Std/Data/HashMap/RawLemmas.lean index 1e910ffd8abd..5d13c1ada9e6 100644 --- a/src/Std/Data/HashMap/RawLemmas.lean +++ b/src/Std/Data/HashMap/RawLemmas.lean @@ -3554,9 +3554,6 @@ theorem getD_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] end map -instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| DHashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out - attribute [simp] contains_eq_false_iff_not_mem end Raw diff --git a/src/Std/Data/HashSet.lean b/src/Std/Data/HashSet.lean index c81d347feef5..adc683d5d71b 100644 --- a/src/Std/Data/HashSet.lean +++ b/src/Std/Data/HashSet.lean @@ -10,3 +10,4 @@ public import Std.Data.HashSet.Basic public import Std.Data.HashSet.Iterator public import Std.Data.HashSet.Lemmas public import Std.Data.HashSet.IteratorLemmas +public import Std.Data.HashSet.DecidableEquiv diff --git a/src/Std/Data/HashSet/DecidableEquiv.lean b/src/Std/Data/HashSet/DecidableEquiv.lean new file mode 100644 index 000000000000..e85c7212094b --- /dev/null +++ b/src/Std/Data/HashSet/DecidableEquiv.lean @@ -0,0 +1,23 @@ +/- +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wojciech Różowski +-/ +module + +prelude +public import Std.Data.HashMap.DecidableEquiv +public import Std.Data.HashSet.Basic + +public section + +/-! +# Decidable equivalence for `HashSet` +-/ + +namespace Std.HashSet + +instance {α : Type u} [DecidableEq α] [Hashable α] (m₁ m₂ : HashSet α) : Decidable (m₁ ~m m₂) := + @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| HashMap.instDecidableEquivOfDecidableEq m₁.inner m₂.inner + +end Std.HashSet diff --git a/src/Std/Data/HashSet/Lemmas.lean b/src/Std/Data/HashSet/Lemmas.lean index c2320da1dcd6..78bbc0528b7e 100644 --- a/src/Std/Data/HashSet/Lemmas.lean +++ b/src/Std/Data/HashSet/Lemmas.lean @@ -1536,8 +1536,5 @@ theorem getD_filter [EquivBEq α] [LawfulHashable α] end filter -instance {α : Type u} [DecidableEq α] [Hashable α] (m₁ m₂ : HashSet α) : Decidable (m₁ ~m m₂) := - @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| HashMap.instDecidableEquivOfDecidableEq m₁.inner m₂.inner - attribute [simp] contains_eq_false_iff_not_mem end Std.HashSet diff --git a/src/Std/Data/HashSet/RawDecidableEquiv.lean b/src/Std/Data/HashSet/RawDecidableEquiv.lean new file mode 100644 index 000000000000..3536734ce5aa --- /dev/null +++ b/src/Std/Data/HashSet/RawDecidableEquiv.lean @@ -0,0 +1,23 @@ +/- +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Wojciech Różowski +-/ +module + +prelude +public import Std.Data.HashMap.RawDecidableEquiv +public import Std.Data.HashSet.Raw + +public section + +/-! +# Decidable equivalence for `HashSet.Raw` +-/ + +namespace Std.HashSet.Raw + +instance {α : Type u} [DecidableEq α] [Hashable α] {m₁ m₂ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := + @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| HashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out + +end Std.HashSet.Raw diff --git a/src/Std/Data/HashSet/RawLemmas.lean b/src/Std/Data/HashSet/RawLemmas.lean index beff0f35ced2..f8d8742300fc 100644 --- a/src/Std/Data/HashSet/RawLemmas.lean +++ b/src/Std/Data/HashSet/RawLemmas.lean @@ -1607,9 +1607,6 @@ theorem get_filter [EquivBEq α] [LawfulHashable α] end filter -instance {α : Type u} [DecidableEq α] [Hashable α] {m₁ m₂ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| HashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out - attribute [simp] contains_eq_false_iff_not_mem end Raw From 8bd52959e4e08f8ec01558b487a3d21ecd7801a9 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 3 Dec 2025 14:25:47 +0000 Subject: [PATCH 48/72] chore: fix orphaned modules issue --- src/Std/Data.lean | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Std/Data.lean b/src/Std/Data.lean index 9978bf2a998e..47f60a9ff28b 100644 --- a/src/Std/Data.lean +++ b/src/Std/Data.lean @@ -23,11 +23,11 @@ public import Std.Data.ExtTreeSet -- the well-formedness invariant, so we need to additionally import the files that deal with the -- unbundled version public import Std.Data.DHashMap.RawLemmas -public import Std.Data.DHashMap.DecidableEquiv +public import Std.Data.DHashMap.RawDecidableEquiv public import Std.Data.HashMap.RawLemmas -public import Std.Data.HashMap.DecidableEquiv +public import Std.Data.HashMap.RawDecidableEquiv public import Std.Data.HashSet.RawLemmas -public import Std.Data.HashSet.DecidableEquiv +public import Std.Data.HashSet.RawDecidableEquiv public import Std.Data.DTreeMap.Raw public import Std.Data.TreeMap.Raw public import Std.Data.TreeSet.Raw From e8d3749498bed56de39dad2116a07345c3664e4b Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 3 Dec 2025 15:53:18 +0000 Subject: [PATCH 49/72] Respond to Markus' comments --- src/Std/Data/DHashMap/DecidableEquiv.lean | 3 +-- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 4 ++-- src/Std/Data/DHashMap/RawDecidableEquiv.lean | 2 +- src/Std/Data/ExtDHashMap/Basic.lean | 2 +- src/Std/Data/ExtHashMap/Basic.lean | 2 +- src/Std/Data/ExtHashSet/Basic.lean | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Std/Data/DHashMap/DecidableEquiv.lean b/src/Std/Data/DHashMap/DecidableEquiv.lean index 13baaa636282..8201f1bf80fb 100644 --- a/src/Std/Data/DHashMap/DecidableEquiv.lean +++ b/src/Std/Data/DHashMap/DecidableEquiv.lean @@ -18,7 +18,6 @@ open Std.DHashMap.Internal namespace Std.DHashMap -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| - @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| Raw₀.decidable_equiv ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 end Std.DHashMap diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 82b7f5d43f2a..3925fbf704b0 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -5140,10 +5140,10 @@ end Raw₀ namespace Raw₀ /-- Internal implementation detail -/ -def Equiv.decide [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] +def decidable_equiv [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : Raw₀ α β) (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : Decidable (m₁.1.Equiv m₂.1) := by have decBEq : Decidable (Raw₀.beq m₁ m₂ = true) := inferInstance - apply @decidable_of_decidable_of_iff (Raw₀.beq m₁ m₂ = true) (m₁.1.Equiv m₂.1) decBEq + apply decidable_of_iff (Raw₀.beq m₁ m₂ = true) constructor · apply Raw₀.equiv_of_beq h₁ h₂ · apply Raw₀.Equiv.beq h₁ h₂ diff --git a/src/Std/Data/DHashMap/RawDecidableEquiv.lean b/src/Std/Data/DHashMap/RawDecidableEquiv.lean index b603779d8a86..8515e43dfb2e 100644 --- a/src/Std/Data/DHashMap/RawDecidableEquiv.lean +++ b/src/Std/Data/DHashMap/RawDecidableEquiv.lean @@ -19,6 +19,6 @@ open Std.DHashMap.Internal namespace Std.DHashMap.Raw instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - @Raw₀.Equiv.decide _ _ _ _ _ ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ + Raw₀.decidable_equiv ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ end Std.DHashMap.Raw diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index a448963a8eef..e08ab2836fc6 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -384,7 +384,7 @@ instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : LawfulBE apply sound <| DHashMap.equiv_of_beq hyp instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] : DecidableEq (ExtDHashMap α β) := - fun m₁ m₂ => @decidable_of_decidable_of_iff (m₁ == m₂) _ _ ⟨by simp, by simp⟩ + fun m₁ m₂ => decidable_of_iff (m₁ == m₂) ⟨by simp, by simp⟩ namespace Const diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index 0043b0b2eead..04a7b4bfe726 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -265,7 +265,7 @@ instance [LawfulBEq α] [BEq β] [LawfulBEq β] : LawfulBEq (ExtHashMap α β) w exact ExtDHashMap.Const.eq_of_beq _ _ hyp instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] : DecidableEq (ExtDHashMap α β) := - fun m₁ m₂ => @decidable_of_decidable_of_iff (m₁ == m₂) _ _ ⟨by simp, by simp⟩ + fun m₁ m₂ => decidable_of_iff (m₁ == m₂) ⟨by simp, by simp⟩ @[inline, inherit_doc ExtDHashMap.inter] def inter [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashMap α β) : ExtHashMap α β := ⟨ExtDHashMap.inter m₁.inner m₂.inner⟩ diff --git a/src/Std/Data/ExtHashSet/Basic.lean b/src/Std/Data/ExtHashSet/Basic.lean index 98119f256aae..cabb6f5cff67 100644 --- a/src/Std/Data/ExtHashSet/Basic.lean +++ b/src/Std/Data/ExtHashSet/Basic.lean @@ -225,7 +225,7 @@ instance [LawfulBEq α] : LawfulBEq (ExtHashSet α) where exact ExtDHashMap.Const.eq_of_beq_unit _ _ hyp instance {α : Type u} [DecidableEq α] [Hashable α] : DecidableEq (ExtHashSet α) := - fun m₁ m₂ => @decidable_of_decidable_of_iff (m₁ == m₂) _ _ ⟨by simp, by simp⟩ + fun m₁ m₂ => decidable_of_iff (m₁ == m₂) ⟨by simp, by simp⟩ /-- Computes the intersection of the given hash sets. From 3785fa8317c0ce4bafd26b0418083283ba77fd56 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Wed, 3 Dec 2025 21:38:07 +0000 Subject: [PATCH 50/72] Resolve Markus' comments --- src/Std/Data/DHashMap/DecidableEquiv.lean | 2 +- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 3 +-- src/Std/Data/DHashMap/RawDecidableEquiv.lean | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Std/Data/DHashMap/DecidableEquiv.lean b/src/Std/Data/DHashMap/DecidableEquiv.lean index 8201f1bf80fb..524daa8d6adb 100644 --- a/src/Std/Data/DHashMap/DecidableEquiv.lean +++ b/src/Std/Data/DHashMap/DecidableEquiv.lean @@ -18,6 +18,6 @@ open Std.DHashMap.Internal namespace Std.DHashMap -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| Raw₀.decidable_equiv ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| Raw₀.decidableEquiv ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 end Std.DHashMap diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 3925fbf704b0..40506342f70c 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -5140,9 +5140,8 @@ end Raw₀ namespace Raw₀ /-- Internal implementation detail -/ -def decidable_equiv [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] +def decidableEquiv [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : Raw₀ α β) (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : Decidable (m₁.1.Equiv m₂.1) := by - have decBEq : Decidable (Raw₀.beq m₁ m₂ = true) := inferInstance apply decidable_of_iff (Raw₀.beq m₁ m₂ = true) constructor · apply Raw₀.equiv_of_beq h₁ h₂ diff --git a/src/Std/Data/DHashMap/RawDecidableEquiv.lean b/src/Std/Data/DHashMap/RawDecidableEquiv.lean index 8515e43dfb2e..51a8f9874705 100644 --- a/src/Std/Data/DHashMap/RawDecidableEquiv.lean +++ b/src/Std/Data/DHashMap/RawDecidableEquiv.lean @@ -19,6 +19,6 @@ open Std.DHashMap.Internal namespace Std.DHashMap.Raw instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - Raw₀.decidable_equiv ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ + Raw₀.decidableEquiv ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ end Std.DHashMap.Raw From 3bd07be32f56ce7ad65b577e8142db7533d48799 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 4 Dec 2025 10:56:25 +0000 Subject: [PATCH 51/72] Refactor --- src/Init/Data/List/Perm.lean | 9 +++++++++ src/Std/Data/ExtDHashMap/Basic.lean | 6 +++--- src/Std/Data/ExtHashSet/Basic.lean | 6 +++--- src/Std/Data/HashMap/Raw.lean | 1 - src/Std/Data/Internal/List/Associative.lean | 13 ++----------- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/Init/Data/List/Perm.lean b/src/Init/Data/List/Perm.lean index c29674071cfd..f67d05975514 100644 --- a/src/Init/Data/List/Perm.lean +++ b/src/Init/Data/List/Perm.lean @@ -601,6 +601,15 @@ theorem sum_nat {l₁ l₂ : List Nat} (h : l₁ ~ l₂) : l₁.sum = l₂.sum : | swap => simpa [List.sum_cons] using Nat.add_left_comm .. | trans _ _ ih₁ ih₂ => simp [ih₁, ih₂] +theorem all_eq {l₁ l₂ : List α} {f : α → Bool} (hp : l₁.Perm l₂) : l₁.all f = l₂.all f := by + rw [Bool.eq_iff_iff, Bool.eq_iff_iff, List.all_eq_true, List.all_eq_true] + simp only [iff_true] + constructor + · intro hyp e mem + exact hyp e (@Perm.mem_iff _ e l₁ l₂ hp |>.2 mem) + · intro hyp e mem + exact hyp e (@Perm.mem_iff _ e l₂ l₁ hp.symm |>.2 mem) + grind_pattern Perm.sum_nat => l₁ ~ l₂, l₁.sum grind_pattern Perm.sum_nat => l₁ ~ l₂, l₂.sum diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index 0ae70093fe23..90464efc405e 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -409,14 +409,14 @@ end Const namespace Const @[inline, inherit_doc DHashMap.beq] -def beq_unit [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) : Bool := lift₂ (fun x y : DHashMap α fun _ => Unit => DHashMap.Const.beq x y) +def beqUnit [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) : Bool := lift₂ (fun x y : DHashMap α fun _ => Unit => DHashMap.Const.beq x y) (fun _ _ _ _ => DHashMap.Const.Equiv.beq_congr) m₁ m₂ -theorem beq_unit_of_eq [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : m₁ = m₂) : Const.beq_unit m₁ m₂ := by +theorem beqUnit_of_eq [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : m₁ = m₂) : Const.beqUnit m₁ m₂ := by apply beq_of_eq exact h -theorem eq_of_beq_unit [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : Const.beq_unit m₁ m₂) : m₁ = m₂ := by +theorem eq_of_beqUnit [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : Const.beqUnit m₁ m₂) : m₁ = m₂ := by apply eq_of_beq exact h diff --git a/src/Std/Data/ExtHashSet/Basic.lean b/src/Std/Data/ExtHashSet/Basic.lean index 6609ba6e813b..347e7c99a390 100644 --- a/src/Std/Data/ExtHashSet/Basic.lean +++ b/src/Std/Data/ExtHashSet/Basic.lean @@ -205,7 +205,7 @@ def union [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashSet α) : ExtHas instance [EquivBEq α] [LawfulHashable α] : Union (ExtHashSet α) := ⟨union⟩ @[inline, inherit_doc ExtHashMap.beq] -def beq [LawfulBEq α] (m₁ m₂ : ExtHashSet α) : Bool := ExtDHashMap.Const.beq_unit m₁.inner.inner m₂.inner.inner +def beq [LawfulBEq α] (m₁ m₂ : ExtHashSet α) : Bool := ExtDHashMap.Const.beqUnit m₁.inner.inner m₂.inner.inner instance [LawfulBEq α] : BEq (ExtHashSet α) := ⟨beq⟩ @@ -214,7 +214,7 @@ instance [LawfulBEq α] : ReflBEq (ExtHashSet α) where intro a cases a case mk a => - apply ExtDHashMap.Const.beq_unit_of_eq + apply ExtDHashMap.Const.beqUnit_of_eq rfl instance [LawfulBEq α] : LawfulBEq (ExtHashSet α) where @@ -222,7 +222,7 @@ instance [LawfulBEq α] : LawfulBEq (ExtHashSet α) where have ⟨⟨a⟩⟩ := a have ⟨⟨b⟩⟩ := b simp only [mk.injEq, ExtHashMap.mk.injEq] at |- hyp - exact ExtDHashMap.Const.eq_of_beq_unit _ _ hyp + exact ExtDHashMap.Const.eq_of_beqUnit _ _ hyp /-- Computes the intersection of the given hash sets. diff --git a/src/Std/Data/HashMap/Raw.lean b/src/Std/Data/HashMap/Raw.lean index 1a15f72387e1..50f98ca34a9e 100644 --- a/src/Std/Data/HashMap/Raw.lean +++ b/src/Std/Data/HashMap/Raw.lean @@ -256,7 +256,6 @@ def beq {β : Type v} [BEq α] [Hashable α] [BEq β] (m₁ m₂ : Raw α β) : instance [BEq α] [Hashable α] [BEq β] : BEq (Raw α β) := ⟨beq⟩ - section Unverified @[inline, inherit_doc DHashMap.Raw.filterMap] def filterMap {γ : Type w} (f : α → β → Option γ) diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index bbb4f350a8c7..bf28038e122c 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -7703,15 +7703,6 @@ theorem perm_of_beqModel [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, Law rw [Bool.not_eq_true] at hc₂ rw [getValueCast?_eq_none hc₁, getValueCast?_eq_none hc₂] -theorem all_congr [BEq α] {l₁ l₂ : List ((a : α) × β a)} {f : (a : α) × β a → Bool} (hp : l₁.Perm l₂) : l₁.all f = l₂.all f := by - rw [Bool.eq_iff_iff, Bool.eq_iff_iff, List.all_eq_true, List.all_eq_true] - simp only [iff_true] - constructor - · intro hyp ⟨k,v⟩ mem - exact hyp ⟨k,v⟩ (@Perm.mem_iff _ ⟨k,v⟩ l₁ l₂ hp |>.2 mem) - · intro hyp ⟨k,v⟩ mem - exact hyp ⟨k,v⟩ (@Perm.mem_iff _ ⟨k,v⟩ l₂ l₁ hp.symm |>.2 mem) - theorem beqModel_congr [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] {l₁ l₂ l₃ l₄ : List ((a : α) × β a)} (hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by rw [beqModel] @@ -7732,7 +7723,7 @@ theorem beqModel_congr [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] {l₁ l₂ l ext x rw [getValueCast?_of_perm hl p₂] rw [this] - apply all_congr p₁ + apply List.Perm.all_eq p₁ theorem Const.beqModel_congr {β : Type v} [BEq α] [LawfulBEq α] [BEq β] {l₁ l₂ l₃ l₄ : List ((_ : α) × β)} (hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by @@ -7754,7 +7745,7 @@ theorem Const.beqModel_congr {β : Type v} [BEq α] [LawfulBEq α] [BEq β] {l ext x rw [getValue?_of_perm hl p₂] rw [this] - apply all_congr p₁ + apply List.Perm.all_eq p₁ theorem beqModel_eq_constBeqModel {β : Type v} [BEq α] [LawfulBEq α] [BEq β] {l₁ l₂ : List ((_ : α) × β)} : beqModel l₁ l₂ = Const.beqModel l₁ l₂ := by rw [beqModel, Const.beqModel] From 7ef173ea7b1e00b5e5067f2079d76049ff9d66e2 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 4 Dec 2025 11:01:54 +0000 Subject: [PATCH 52/72] Further refactor --- src/Std/Data/DHashMap/RawLemmas.lean | 1 + src/Std/Data/HashSet/Basic.lean | 1 - src/Std/Data/Internal/List/Associative.lean | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index 920a14123836..9d61d06f199d 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -9,6 +9,7 @@ prelude public import Std.Data.DHashMap.Internal.Raw public import Std.Data.DHashMap.Internal.RawLemmas import all Std.Data.DHashMap.Raw + public section /-! diff --git a/src/Std/Data/HashSet/Basic.lean b/src/Std/Data/HashSet/Basic.lean index 8a82e053e0c8..f140b4a4376e 100644 --- a/src/Std/Data/HashSet/Basic.lean +++ b/src/Std/Data/HashSet/Basic.lean @@ -266,7 +266,6 @@ def beq [BEq α] (m₁ m₂ : HashSet α) : Bool := instance [BEq α] : BEq (HashSet α) := ⟨beq⟩ - /-- Computes the difference of the given hash sets. diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index bf28038e122c..12d27595de72 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -3617,7 +3617,7 @@ theorem length_le_length_of_containsKey [BEq α] [EquivBEq α] simp [mem] · exact dl₂ -theorem containsKey_of_subset_of_length_eq [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : α) × β a)} (dl₁ : DistinctKeys l₁) (dl₂ : DistinctKeys l₂) (hl : l₂.length = l₁.length) (hs : ∀ (a : α), containsKey a l₁ → containsKey a l₂) : ∀ (a : α), containsKey a l₂ → containsKey a l₁ := by +theorem containsKey_of_length_eq [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : α) × β a)} (dl₁ : DistinctKeys l₁) (dl₂ : DistinctKeys l₂) (hl : l₂.length = l₁.length) (hs : ∀ (a : α), containsKey a l₁ → containsKey a l₂) : ∀ (a : α), containsKey a l₂ → containsKey a l₁ := by intro a ha apply Classical.byContradiction intro hb @@ -7692,7 +7692,7 @@ theorem perm_of_beqModel [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, Law by_cases hc₂ : containsKey a l₂ case pos => suffices (∀ (a : α), containsKey a l₁ = true → containsKey a l₂ = true) by - rw [@containsKey_of_subset_of_length_eq α β _ _ l₁ l₂ hl₁ hl₂ he.symm this a hc₂] at hc₁ + rw [@containsKey_of_length_eq α β _ _ l₁ l₂ hl₁ hl₂ he.symm this a hc₂] at hc₁ contradiction intro k' mem have := eq_of_beq <| hyp2 k' mem From c04f6842bf2f727d28f1caea8411607ed98cb9f1 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 4 Dec 2025 16:39:00 +0000 Subject: [PATCH 53/72] Resolve Markus' comment --- src/Std/Data/DHashMap/Lemmas.lean | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index 49f2e18fe5f4..69bd83232893 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -1862,15 +1862,10 @@ variable {β : Type v} {m₁ m₂ : DHashMap α (fun _ => β)} [BEq β] theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [ReflBEq β] (h : m₁ ~m m₂) : DHashMap.Const.beq m₁ m₂ := by apply Raw₀.Const.Equiv.beq m₁.2 m₂.2 h.1 -theorem Const.equiv_of_beq [LawfulBEq α] [LawfulBEq β] (h : Const.beq m₁ m₂) : m₁ ~m m₂ := by - constructor - have := @Raw₀.Const.equiv_of_beq α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h - simp only at this - exact this - -theorem Const.Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : DHashMap α (fun _ => β)} : m₁ ~m m₃ → m₂ ~m m₄ → Const.beq m₁ m₂ = Const.beq m₃ m₄ := by - intro h1 h2 - exact @Raw₀.Const.Equiv.beq_congr α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ ⟨m₃.1, m₃.2.size_buckets_pos⟩ ⟨m₄.1, m₄.2.size_buckets_pos⟩ _ m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 +theorem Const.equiv_of_beq [LawfulBEq α] [LawfulBEq β] (h : Const.beq m₁ m₂) : m₁ ~m m₂ := + ⟨Raw₀.Const.equiv_of_beq m₁.2 m₂.2 h⟩ +theorem Const.Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : DHashMap α (fun _ => β)} : m₁ ~m m₃ → m₂ ~m m₄ → Const.beq m₁ m₂ = Const.beq m₃ m₄ := + fun h1 h2 => Raw₀.Const.Equiv.beq_congr m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 end section Union From 3b281d5da56e8e98649de396dc668340499d7458 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Thu, 4 Dec 2025 16:42:17 +0000 Subject: [PATCH 54/72] Remove `beqUnit` --- src/Std/Data/ExtDHashMap/Basic.lean | 16 ---------------- src/Std/Data/ExtHashSet/Basic.lean | 13 +++++-------- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index 90464efc405e..01bcf9930f84 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -406,22 +406,6 @@ theorem eq_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (m₁ m₂ : ExtDHashMa end Const -namespace Const - -@[inline, inherit_doc DHashMap.beq] -def beqUnit [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) : Bool := lift₂ (fun x y : DHashMap α fun _ => Unit => DHashMap.Const.beq x y) - (fun _ _ _ _ => DHashMap.Const.Equiv.beq_congr) m₁ m₂ - -theorem beqUnit_of_eq [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : m₁ = m₂) : Const.beqUnit m₁ m₂ := by - apply beq_of_eq - exact h - -theorem eq_of_beqUnit [LawfulBEq α] (m₁ m₂ : ExtDHashMap α fun _ => Unit) (h : Const.beqUnit m₁ m₂) : m₁ = m₂ := by - apply eq_of_beq - exact h - -end Const - @[inline, inherit_doc DHashMap.inter] def inter [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtDHashMap α β) : ExtDHashMap α β := lift₂ (fun x y : DHashMap α β => mk (x.inter y)) (fun a b c d equiv₁ equiv₂ => by diff --git a/src/Std/Data/ExtHashSet/Basic.lean b/src/Std/Data/ExtHashSet/Basic.lean index 347e7c99a390..a8336fe3b4f1 100644 --- a/src/Std/Data/ExtHashSet/Basic.lean +++ b/src/Std/Data/ExtHashSet/Basic.lean @@ -205,24 +205,21 @@ def union [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashSet α) : ExtHas instance [EquivBEq α] [LawfulHashable α] : Union (ExtHashSet α) := ⟨union⟩ @[inline, inherit_doc ExtHashMap.beq] -def beq [LawfulBEq α] (m₁ m₂ : ExtHashSet α) : Bool := ExtDHashMap.Const.beqUnit m₁.inner.inner m₂.inner.inner +def beq [LawfulBEq α] (m₁ m₂ : ExtHashSet α) : Bool := ExtDHashMap.Const.beq m₁.inner.inner m₂.inner.inner instance [LawfulBEq α] : BEq (ExtHashSet α) := ⟨beq⟩ instance [LawfulBEq α] : ReflBEq (ExtHashSet α) where - rfl := by - intro a - cases a - case mk a => - apply ExtDHashMap.Const.beqUnit_of_eq - rfl + rfl {a} := by + have ⟨a⟩ := a + exact ExtDHashMap.Const.beq_of_eq _ _ rfl instance [LawfulBEq α] : LawfulBEq (ExtHashSet α) where eq_of_beq {a} {b} hyp := by have ⟨⟨a⟩⟩ := a have ⟨⟨b⟩⟩ := b simp only [mk.injEq, ExtHashMap.mk.injEq] at |- hyp - exact ExtDHashMap.Const.eq_of_beqUnit _ _ hyp + exact ExtDHashMap.Const.eq_of_beq _ _ hyp /-- Computes the intersection of the given hash sets. From c47995a3c3adf0dbac60ac5042dc8da7b119b628 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 5 Dec 2025 10:30:15 +0000 Subject: [PATCH 55/72] Weaken the instances for the Const variant --- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 2 +- src/Std/Data/DHashMap/Lemmas.lean | 4 ++-- src/Std/Data/DHashMap/RawLemmas.lean | 2 +- src/Std/Data/ExtDHashMap/Basic.lean | 2 +- src/Std/Data/ExtHashMap/Basic.lean | 2 +- src/Std/Data/ExtHashSet/Basic.lean | 2 +- src/Std/Data/HashMap/Lemmas.lean | 4 ++-- src/Std/Data/HashMap/RawLemmas.lean | 4 ++-- src/Std/Data/HashSet/RawLemmas.lean | 4 ++-- src/Std/Data/Internal/List/Associative.lean | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 7953f8e8ef8d..8bc58a559ea4 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -2610,7 +2610,7 @@ theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] theorem Const.equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : beq m₁ m₂ = true → m₁.1.Equiv m₂.1 := by simp_to_model using List.Const.perm_of_beqModel -theorem Const.Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : Raw₀ α (fun _ => β)} [BEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) (h₃ : m₃.val.WF) (h₄ : m₄.val.WF) : +theorem Const.Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : Raw₀ α (fun _ => β)} [BEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) (h₃ : m₃.val.WF) (h₄ : m₄.val.WF) : m₁.1.Equiv m₃.1 → m₂.1.Equiv m₄.1 → Const.beq m₁ m₂ = Const.beq m₃ m₄ := by simp_to_model using List.Const.beqModel_congr end diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index 2597749d8703..6d257e0cdf2c 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -1868,9 +1868,9 @@ theorem Const.equiv_of_beq [LawfulBEq α] [LawfulBEq β] (h : Const.beq m₁ m simp only at this exact this -theorem Const.Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : DHashMap α (fun _ => β)} : m₁ ~m m₃ → m₂ ~m m₄ → Const.beq m₁ m₂ = Const.beq m₃ m₄ := by +theorem Const.Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : DHashMap α (fun _ => β)} : m₁ ~m m₃ → m₂ ~m m₄ → Const.beq m₁ m₂ = Const.beq m₃ m₄ := by intro h1 h2 - exact @Raw₀.Const.Equiv.beq_congr α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ ⟨m₃.1, m₃.2.size_buckets_pos⟩ ⟨m₄.1, m₄.2.size_buckets_pos⟩ _ m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 + exact @Raw₀.Const.Equiv.beq_congr α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ ⟨m₃.1, m₃.2.size_buckets_pos⟩ ⟨m₄.1, m₄.2.size_buckets_pos⟩ _ m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 end section Union diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index 9d61d06f199d..31212ae069e4 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -3790,7 +3790,7 @@ theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] theorem Const.equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : beq m₁ m₂ = true → m₁ ~m m₂ := by simp_to_raw using Raw₀.Const.equiv_of_beq -theorem Const.Equiv.beq_congr [LawfulBEq α] [BEq β] {m₃ m₄ : Raw α (fun _ => β)} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : +theorem Const.Equiv.beq_congr [EquivBEq α] [LawfulHashable α] [BEq β] {m₃ m₄ : Raw α (fun _ => β)} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : m₁ ~m m₃ → m₂ ~m m₄ → Raw.Const.beq m₁ m₂ = Raw.Const.beq m₃ m₄ := by simp_to_raw intro w1 w2 diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index 01bcf9930f84..8da2ad07cf3a 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -387,7 +387,7 @@ namespace Const variable {β : Type v} @[inline, inherit_doc DHashMap.beq] -def beq [LawfulBEq α] [BEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) : Bool := lift₂ (fun x y : DHashMap α fun _ => β => DHashMap.Const.beq x y) +def beq [EquivBEq α] [LawfulHashable α] [BEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) : Bool := lift₂ (fun x y : DHashMap α fun _ => β => DHashMap.Const.beq x y) (fun _ _ _ _ => DHashMap.Const.Equiv.beq_congr) m₁ m₂ theorem beq_of_eq [LawfulBEq α] [BEq β] [ReflBEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) (h : m₁ = m₂) : Const.beq m₁ m₂ := by diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index 8c2e668a2cca..4e4f3e38d5bd 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -250,7 +250,7 @@ def union [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashMap α β) : Ext instance [EquivBEq α] [LawfulHashable α] : Union (ExtHashMap α β) := ⟨union⟩ @[inline, inherit_doc ExtDHashMap.beq] -def beq [LawfulBEq α] [BEq β] (m₁ m₂ : ExtHashMap α β) : Bool := ExtDHashMap.Const.beq m₁.inner m₂.inner +def beq [EquivBEq α] [LawfulHashable α] [BEq β] (m₁ m₂ : ExtHashMap α β) : Bool := ExtDHashMap.Const.beq m₁.inner m₂.inner instance [LawfulBEq α] [BEq β] : BEq (ExtHashMap α β) := ⟨beq⟩ diff --git a/src/Std/Data/ExtHashSet/Basic.lean b/src/Std/Data/ExtHashSet/Basic.lean index a8336fe3b4f1..f58633877373 100644 --- a/src/Std/Data/ExtHashSet/Basic.lean +++ b/src/Std/Data/ExtHashSet/Basic.lean @@ -205,7 +205,7 @@ def union [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashSet α) : ExtHas instance [EquivBEq α] [LawfulHashable α] : Union (ExtHashSet α) := ⟨union⟩ @[inline, inherit_doc ExtHashMap.beq] -def beq [LawfulBEq α] (m₁ m₂ : ExtHashSet α) : Bool := ExtDHashMap.Const.beq m₁.inner.inner m₂.inner.inner +def beq [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashSet α) : Bool := ExtDHashMap.Const.beq m₁.inner.inner m₂.inner.inner instance [LawfulBEq α] : BEq (ExtHashSet α) := ⟨beq⟩ diff --git a/src/Std/Data/HashMap/Lemmas.lean b/src/Std/Data/HashMap/Lemmas.lean index 423b6469f48c..09ffbc320c47 100644 --- a/src/Std/Data/HashMap/Lemmas.lean +++ b/src/Std/Data/HashMap/Lemmas.lean @@ -1349,13 +1349,13 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] section variable {β : Type v} {m₁ m₂ : HashMap α β} [BEq β] -theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [ReflBEq β] (h : m₁ ~m m₂) : m₁ == m₂ := +theorem Equiv.beq [EquivBEq α] [LawfulHashable α] [ReflBEq β] (h : m₁ ~m m₂) : m₁ == m₂ := DHashMap.Const.Equiv.beq h.1 theorem equiv_of_beq [LawfulBEq α] [LawfulBEq β] (h : m₁ == m₂) : m₁ ~m m₂ := ⟨DHashMap.Const.equiv_of_beq h⟩ -theorem Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : HashMap α β} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun h1 h2 => +theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : HashMap α β} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun h1 h2 => DHashMap.Const.Equiv.beq_congr h1.1 h2.1 end diff --git a/src/Std/Data/HashMap/RawLemmas.lean b/src/Std/Data/HashMap/RawLemmas.lean index f5da73d93d82..f16e29794015 100644 --- a/src/Std/Data/HashMap/RawLemmas.lean +++ b/src/Std/Data/HashMap/RawLemmas.lean @@ -1317,9 +1317,9 @@ theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ theorem equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := fun hyp => ⟨@DHashMap.Raw.Const.equiv_of_beq _ _ _ _ m₁.1 m₂.1 _ _ _ h₁.1 h₂.1 hyp⟩ -theorem Equiv.beq_congr [LawfulBEq α] [BEq β] {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : +theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] [BEq β] {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun hyp1 hyp2 => - @DHashMap.Raw.Const.Equiv.beq_congr _ _ _ _ m₁.1 m₂.1 _ _ m₃.1 m₄.1 h₁.1 h₂.1 h₃.1 h₄.1 hyp1.1 hyp2.1 + @DHashMap.Raw.Const.Equiv.beq_congr _ _ _ _ m₁.1 m₂.1 _ _ _ m₃.1 m₄.1 h₁.1 h₂.1 h₃.1 h₄.1 hyp1.1 hyp2.1 end diff --git a/src/Std/Data/HashSet/RawLemmas.lean b/src/Std/Data/HashSet/RawLemmas.lean index f8d8742300fc..21a40875f86e 100644 --- a/src/Std/Data/HashSet/RawLemmas.lean +++ b/src/Std/Data/HashSet/RawLemmas.lean @@ -823,9 +823,9 @@ theorem Equiv.beq [LawfulHashable α] [EquivBEq α] (h₁ : m₁.WF) (h₂ : m theorem equiv_of_beq [LawfulBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := fun hyp => ⟨@HashMap.Raw.equiv_of_beq _ _ _ _ m₁.1 m₂.1 _ _ _ h₁.1 h₂.1 hyp⟩ -theorem Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : +theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun hyp1 hyp2 => - @HashMap.Raw.Equiv.beq_congr _ _ _ _ m₁.1 m₂.1 _ _ m₃.1 m₄.1 h₁.1 h₂.1 h₃.1 h₄.1 hyp1.1 hyp2.1 + @HashMap.Raw.Equiv.beq_congr _ _ _ _ m₁.1 m₂.1 _ _ _ m₃.1 m₄.1 h₁.1 h₂.1 h₃.1 h₄.1 hyp1.1 hyp2.1 end diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 12d27595de72..3fda1030af1d 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -7725,7 +7725,7 @@ theorem beqModel_congr [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] {l₁ l₂ l rw [this] apply List.Perm.all_eq p₁ -theorem Const.beqModel_congr {β : Type v} [BEq α] [LawfulBEq α] [BEq β] {l₁ l₂ l₃ l₄ : List ((_ : α) × β)} +theorem Const.beqModel_congr {β : Type v} [BEq α] [EquivBEq α] [BEq β] {l₁ l₂ l₃ l₄ : List ((_ : α) × β)} (hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by rw [beqModel] split From 8adfa66929af437262f2d983d80d1f18f8651bd6 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 5 Dec 2025 12:28:14 +0000 Subject: [PATCH 56/72] Cleanup --- src/Std/Data/DHashMap/Lemmas.lean | 34 ++++++++++++------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index 6d257e0cdf2c..558215df1442 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -1841,19 +1841,15 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] section BEq variable {m₁ m₂ : DHashMap α β} [LawfulBEq α] [∀ k, BEq (β k)] -theorem Equiv.beq [∀ k, ReflBEq (β k)] (h : m₁ ~m m₂) : m₁ == m₂ := by - simp [BEq.beq] - apply Raw₀.Equiv.beq m₁.2 m₂.2 h.1 - -theorem equiv_of_beq [∀ k, LawfulBEq (β k)] (h : m₁ == m₂) : m₁ ~m m₂ := by - constructor - have := @Raw₀.equiv_of_beq α β _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h - simp only at this - exact this - -theorem Equiv.beq_congr {m₃ m₄ : DHashMap α β} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := by - intro h1 h2 - exact @Raw₀.Equiv.beq_congr α β _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ ⟨m₃.1, m₃.2.size_buckets_pos⟩ ⟨m₄.1, m₄.2.size_buckets_pos⟩ m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 +theorem Equiv.beq [∀ k, ReflBEq (β k)] (h : m₁ ~m m₂) : m₁ == m₂ := + Raw₀.Equiv.beq m₁.2 m₂.2 h.1 + +theorem equiv_of_beq [∀ k, LawfulBEq (β k)] (h : m₁ == m₂) : m₁ ~m m₂ := + ⟨@Raw₀.equiv_of_beq α β _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h⟩ + +theorem Equiv.beq_congr {m₃ m₄ : DHashMap α β} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun h1 h2 => + @Raw₀.Equiv.beq_congr α β _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ ⟨m₃.1, m₃.2.size_buckets_pos⟩ ⟨m₄.1, m₄.2.size_buckets_pos⟩ m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 + end BEq section @@ -1862,15 +1858,11 @@ variable {β : Type v} {m₁ m₂ : DHashMap α (fun _ => β)} [BEq β] theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [ReflBEq β] (h : m₁ ~m m₂) : DHashMap.Const.beq m₁ m₂ := by apply Raw₀.Const.Equiv.beq m₁.2 m₂.2 h.1 -theorem Const.equiv_of_beq [LawfulBEq α] [LawfulBEq β] (h : Const.beq m₁ m₂) : m₁ ~m m₂ := by - constructor - have := @Raw₀.Const.equiv_of_beq α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h - simp only at this - exact this +theorem Const.equiv_of_beq [LawfulBEq α] [LawfulBEq β] (h : Const.beq m₁ m₂) : m₁ ~m m₂ := + ⟨@Raw₀.Const.equiv_of_beq α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h⟩ -theorem Const.Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : DHashMap α (fun _ => β)} : m₁ ~m m₃ → m₂ ~m m₄ → Const.beq m₁ m₂ = Const.beq m₃ m₄ := by - intro h1 h2 - exact @Raw₀.Const.Equiv.beq_congr α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ ⟨m₃.1, m₃.2.size_buckets_pos⟩ ⟨m₄.1, m₄.2.size_buckets_pos⟩ _ m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 +theorem Const.Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : DHashMap α (fun _ => β)} : m₁ ~m m₃ → m₂ ~m m₄ → Const.beq m₁ m₂ = Const.beq m₃ m₄ := fun h1 h2 => + @Raw₀.Const.Equiv.beq_congr α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ ⟨m₃.1, m₃.2.size_buckets_pos⟩ ⟨m₄.1, m₄.2.size_buckets_pos⟩ _ m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 end section Union From 81ca6a54fa5440131dc5ffebe22469e43d3a7c97 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 5 Dec 2025 12:57:11 +0000 Subject: [PATCH 57/72] Further cleanup --- src/Std/Data/DHashMap/Lemmas.lean | 17 ++++++------ src/Std/Data/ExtDHashMap/Basic.lean | 41 +++++++++-------------------- src/Std/Data/HashMap/RawLemmas.lean | 12 ++++----- src/Std/Data/HashSet/Lemmas.lean | 4 +-- src/Std/Data/HashSet/RawLemmas.lean | 13 +++++---- 5 files changed, 35 insertions(+), 52 deletions(-) diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index 558215df1442..d44bf1765841 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -1845,24 +1845,25 @@ theorem Equiv.beq [∀ k, ReflBEq (β k)] (h : m₁ ~m m₂) : m₁ == m₂ := Raw₀.Equiv.beq m₁.2 m₂.2 h.1 theorem equiv_of_beq [∀ k, LawfulBEq (β k)] (h : m₁ == m₂) : m₁ ~m m₂ := - ⟨@Raw₀.equiv_of_beq α β _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h⟩ + ⟨Raw₀.equiv_of_beq m₁.2 m₂.2 h⟩ -theorem Equiv.beq_congr {m₃ m₄ : DHashMap α β} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun h1 h2 => - @Raw₀.Equiv.beq_congr α β _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ ⟨m₃.1, m₃.2.size_buckets_pos⟩ ⟨m₄.1, m₄.2.size_buckets_pos⟩ m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 +theorem Equiv.beq_congr {m₃ m₄ : DHashMap α β} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := + fun h1 h2 => Raw₀.Equiv.beq_congr m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 end BEq section variable {β : Type v} {m₁ m₂ : DHashMap α (fun _ => β)} [BEq β] -theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [ReflBEq β] (h : m₁ ~m m₂) : DHashMap.Const.beq m₁ m₂ := by - apply Raw₀.Const.Equiv.beq m₁.2 m₂.2 h.1 +theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [ReflBEq β] (h : m₁ ~m m₂) : DHashMap.Const.beq m₁ m₂ := + Raw₀.Const.Equiv.beq m₁.2 m₂.2 h.1 theorem Const.equiv_of_beq [LawfulBEq α] [LawfulBEq β] (h : Const.beq m₁ m₂) : m₁ ~m m₂ := - ⟨@Raw₀.Const.equiv_of_beq α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ _ m₁.2 m₂.2 h⟩ + ⟨Raw₀.Const.equiv_of_beq m₁.2 m₂.2 h⟩ + +theorem Const.Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : DHashMap α (fun _ => β)} : m₁ ~m m₃ → m₂ ~m m₄ → Const.beq m₁ m₂ = Const.beq m₃ m₄ := + fun h1 h2 => Raw₀.Const.Equiv.beq_congr m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 -theorem Const.Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : DHashMap α (fun _ => β)} : m₁ ~m m₃ → m₂ ~m m₄ → Const.beq m₁ m₂ = Const.beq m₃ m₄ := fun h1 h2 => - @Raw₀.Const.Equiv.beq_congr α _ _ _ ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ _ _ ⟨m₃.1, m₃.2.size_buckets_pos⟩ ⟨m₄.1, m₄.2.size_buckets_pos⟩ _ m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 end section Union diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index 8da2ad07cf3a..d0c39721f94f 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -363,46 +363,29 @@ def union [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtDHashMap α β) : Ex instance [EquivBEq α] [LawfulHashable α] : Union (ExtDHashMap α β) := ⟨union⟩ @[inline, inherit_doc DHashMap.beq] -def beq [LawfulBEq α] [∀ k, BEq (β k)] (m₁ m₂ : ExtDHashMap α β) : Bool := lift₂ (fun x y : DHashMap α β => x.beq y) - (fun _ _ _ _ => DHashMap.Equiv.beq_congr) m₁ m₂ +def beq [LawfulBEq α] [∀ k, BEq (β k)] (m₁ m₂ : ExtDHashMap α β) : Bool := + lift₂ (fun x y : DHashMap α β => x.beq y) (fun _ _ _ _ => DHashMap.Equiv.beq_congr) m₁ m₂ instance [LawfulBEq α] [∀ k, BEq (β k)] : BEq (ExtDHashMap α β) := ⟨beq⟩ instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : ReflBEq (ExtDHashMap α β) where - rfl {a} := by - induction a - case mk a => - apply DHashMap.Equiv.beq - · apply DHashMap.Equiv.refl + rfl {a} := a.inductionOn fun x => DHashMap.Equiv.beq <| DHashMap.Equiv.refl x instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : LawfulBEq (ExtDHashMap α β) where - eq_of_beq {m₁} {m₂} hyp := by - induction m₁ - case mk a => - induction m₂ - case mk b => - apply sound <| DHashMap.equiv_of_beq hyp + eq_of_beq {m₁} {m₂} := m₁.inductionOn₂ m₂ fun _ _ hyp => sound <| DHashMap.equiv_of_beq hyp namespace Const variable {β : Type v} @[inline, inherit_doc DHashMap.beq] -def beq [EquivBEq α] [LawfulHashable α] [BEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) : Bool := lift₂ (fun x y : DHashMap α fun _ => β => DHashMap.Const.beq x y) - (fun _ _ _ _ => DHashMap.Const.Equiv.beq_congr) m₁ m₂ - -theorem beq_of_eq [LawfulBEq α] [BEq β] [ReflBEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) (h : m₁ = m₂) : Const.beq m₁ m₂ := by - induction m₁ - case mk a => - induction m₂ - case mk b => - exact DHashMap.Const.Equiv.beq <| exact h - -theorem eq_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) (h : Const.beq m₁ m₂) : m₁ = m₂ := by - induction m₁ - case mk a => - induction m₂ - case mk b => - exact sound <| DHashMap.Const.equiv_of_beq h +def beq [EquivBEq α] [LawfulHashable α] [BEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) : Bool := + lift₂ (fun x y : DHashMap α fun _ => β => DHashMap.Const.beq x y) (fun _ _ _ _ => DHashMap.Const.Equiv.beq_congr) m₁ m₂ + +theorem beq_of_eq [LawfulBEq α] [BEq β] [ReflBEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) : m₁ = m₂ → Const.beq m₁ m₂ := + m₁.inductionOn₂ m₂ fun _ _ h => DHashMap.Const.Equiv.beq <| exact h + +theorem eq_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) : Const.beq m₁ m₂ → m₁ = m₂ := + m₁.inductionOn₂ m₂ fun _ _ h => sound <| DHashMap.Const.equiv_of_beq h end Const diff --git a/src/Std/Data/HashMap/RawLemmas.lean b/src/Std/Data/HashMap/RawLemmas.lean index f16e29794015..09c10f821269 100644 --- a/src/Std/Data/HashMap/RawLemmas.lean +++ b/src/Std/Data/HashMap/RawLemmas.lean @@ -1311,15 +1311,15 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] (h : m.W section variable {β : Type v} {m₁ m₂ : Raw α β} -theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → m₁ == m₂ := fun hyp => - @DHashMap.Raw.Const.Equiv.beq _ _ _ _ m₁.1 m₂.1 _ _ _ _ h₁.1 h₂.1 hyp.1 +theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → m₁ == m₂ := + fun hyp => DHashMap.Raw.Const.Equiv.beq h₁.1 h₂.1 hyp.1 -theorem equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := fun hyp => - ⟨@DHashMap.Raw.Const.equiv_of_beq _ _ _ _ m₁.1 m₂.1 _ _ _ h₁.1 h₂.1 hyp⟩ +theorem equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := + fun hyp => ⟨DHashMap.Raw.Const.equiv_of_beq h₁.1 h₂.1 hyp⟩ theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] [BEq β] {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : - m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun hyp1 hyp2 => - @DHashMap.Raw.Const.Equiv.beq_congr _ _ _ _ m₁.1 m₂.1 _ _ _ m₃.1 m₄.1 h₁.1 h₂.1 h₃.1 h₄.1 hyp1.1 hyp2.1 + m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := + fun hyp1 hyp2 => DHashMap.Raw.Const.Equiv.beq_congr h₁.1 h₂.1 h₃.1 h₄.1 hyp1.1 hyp2.1 end diff --git a/src/Std/Data/HashSet/Lemmas.lean b/src/Std/Data/HashSet/Lemmas.lean index f54aa8f59ee1..0779a90f3fc8 100644 --- a/src/Std/Data/HashSet/Lemmas.lean +++ b/src/Std/Data/HashSet/Lemmas.lean @@ -791,8 +791,8 @@ theorem Equiv.beq [LawfulHashable α] [EquivBEq α] (h : m₁ ~m m₂) : m₁ == theorem equiv_of_beq [LawfulBEq α] (h : m₁ == m₂) : m₁ ~m m₂ := ⟨HashMap.equiv_of_beq h⟩ -theorem Equiv.beq_congr [LawfulBEq α] {m₃ m₄ : HashSet α} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun h1 h2 => - HashMap.Equiv.beq_congr h1.1 h2.1 +theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : HashSet α} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := + fun h1 h2 => HashMap.Equiv.beq_congr h1.1 h2.1 end diff --git a/src/Std/Data/HashSet/RawLemmas.lean b/src/Std/Data/HashSet/RawLemmas.lean index 21a40875f86e..70ad87f76b2f 100644 --- a/src/Std/Data/HashSet/RawLemmas.lean +++ b/src/Std/Data/HashSet/RawLemmas.lean @@ -817,15 +817,14 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] (h : m.W section variable {m₁ m₂ : Raw α} -theorem Equiv.beq [LawfulHashable α] [EquivBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := fun hyp => - @HashMap.Raw.Equiv.beq _ _ _ _ m₁.1 m₂.1 _ _ _ _ h₁.1 h₂.1 hyp.1 +theorem Equiv.beq [LawfulHashable α] [EquivBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := + fun hyp => HashMap.Raw.Equiv.beq h₁.1 h₂.1 hyp.1 -theorem equiv_of_beq [LawfulBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := fun hyp => - ⟨@HashMap.Raw.equiv_of_beq _ _ _ _ m₁.1 m₂.1 _ _ _ h₁.1 h₂.1 hyp⟩ +theorem equiv_of_beq [LawfulBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := + fun hyp => ⟨HashMap.Raw.equiv_of_beq h₁.1 h₂.1 hyp⟩ -theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : - m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun hyp1 hyp2 => - @HashMap.Raw.Equiv.beq_congr _ _ _ _ m₁.1 m₂.1 _ _ _ m₃.1 m₄.1 h₁.1 h₂.1 h₃.1 h₄.1 hyp1.1 hyp2.1 +theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := + fun hyp1 hyp2 => HashMap.Raw.Equiv.beq_congr h₁.1 h₂.1 h₃.1 h₄.1 hyp1.1 hyp2.1 end From b1ed589d500ce5f2560a6992e12505309c6445f8 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 5 Dec 2025 13:55:26 +0000 Subject: [PATCH 58/72] Further cleanup --- src/Std/Data/DHashMap/Lemmas.lean | 2 +- src/Std/Data/ExtDHashMap/Basic.lean | 9 +++------ src/Std/Data/ExtHashMap/Basic.lean | 13 ++++++------- src/Std/Data/ExtHashSet/Basic.lean | 16 ++++++---------- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index d44bf1765841..80a288f27208 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -1855,7 +1855,7 @@ end BEq section variable {β : Type v} {m₁ m₂ : DHashMap α (fun _ => β)} [BEq β] -theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [ReflBEq β] (h : m₁ ~m m₂) : DHashMap.Const.beq m₁ m₂ := +theorem Const.Equiv.beq [EquivBEq α] [LawfulHashable α] [ReflBEq β] (h : m₁ ~m m₂) : DHashMap.Const.beq m₁ m₂ := Raw₀.Const.Equiv.beq m₁.2 m₂.2 h.1 theorem Const.equiv_of_beq [LawfulBEq α] [LawfulBEq β] (h : Const.beq m₁ m₂) : m₁ ~m m₂ := diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index d0c39721f94f..3f4a21fd1f48 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -362,11 +362,8 @@ def union [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtDHashMap α β) : Ex instance [EquivBEq α] [LawfulHashable α] : Union (ExtDHashMap α β) := ⟨union⟩ -@[inline, inherit_doc DHashMap.beq] -def beq [LawfulBEq α] [∀ k, BEq (β k)] (m₁ m₂ : ExtDHashMap α β) : Bool := - lift₂ (fun x y : DHashMap α β => x.beq y) (fun _ _ _ _ => DHashMap.Equiv.beq_congr) m₁ m₂ - -instance [LawfulBEq α] [∀ k, BEq (β k)] : BEq (ExtDHashMap α β) := ⟨beq⟩ +instance [LawfulBEq α] [∀ k, BEq (β k)] : BEq (ExtDHashMap α β) where + beq m₁ m₂ := lift₂ (fun x y : DHashMap α β => x.beq y) (fun _ _ _ _ => DHashMap.Equiv.beq_congr) m₁ m₂ instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : ReflBEq (ExtDHashMap α β) where rfl {a} := a.inductionOn fun x => DHashMap.Equiv.beq <| DHashMap.Equiv.refl x @@ -381,7 +378,7 @@ variable {β : Type v} def beq [EquivBEq α] [LawfulHashable α] [BEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) : Bool := lift₂ (fun x y : DHashMap α fun _ => β => DHashMap.Const.beq x y) (fun _ _ _ _ => DHashMap.Const.Equiv.beq_congr) m₁ m₂ -theorem beq_of_eq [LawfulBEq α] [BEq β] [ReflBEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) : m₁ = m₂ → Const.beq m₁ m₂ := +theorem beq_of_eq [EquivBEq α] [LawfulHashable α] [BEq β] [ReflBEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) : m₁ = m₂ → Const.beq m₁ m₂ := m₁.inductionOn₂ m₂ fun _ _ h => DHashMap.Const.Equiv.beq <| exact h theorem eq_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) : Const.beq m₁ m₂ → m₁ = m₂ := diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index 4e4f3e38d5bd..f9fef7d90c59 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -249,16 +249,15 @@ def union [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashMap α β) : Ext instance [EquivBEq α] [LawfulHashable α] : Union (ExtHashMap α β) := ⟨union⟩ -@[inline, inherit_doc ExtDHashMap.beq] -def beq [EquivBEq α] [LawfulHashable α] [BEq β] (m₁ m₂ : ExtHashMap α β) : Bool := ExtDHashMap.Const.beq m₁.inner m₂.inner +instance [EquivBEq α] [LawfulHashable α] [BEq β] : BEq (ExtHashMap α β) where + beq m₁ m₂ := ExtDHashMap.Const.beq m₁.inner m₂.inner -instance [LawfulBEq α] [BEq β] : BEq (ExtHashMap α β) := ⟨beq⟩ - -instance [LawfulBEq α] [BEq β] [ReflBEq β] : ReflBEq (ExtHashMap α β) where - rfl := by intro a; apply ExtDHashMap.Const.beq_of_eq; rfl +instance [EquivBEq α] [LawfulHashable α] [BEq β] [ReflBEq β] : ReflBEq (ExtHashMap α β) where + rfl := ExtDHashMap.Const.beq_of_eq _ _ rfl instance [LawfulBEq α] [BEq β] [LawfulBEq β] : LawfulBEq (ExtHashMap α β) where - eq_of_beq {a} {b} hyp := by + eq_of_beq {a} {b} hyp := + by have ⟨a⟩ := a have ⟨b⟩ := b simp only [mk.injEq] at |- hyp diff --git a/src/Std/Data/ExtHashSet/Basic.lean b/src/Std/Data/ExtHashSet/Basic.lean index f58633877373..cbf54e7f83b4 100644 --- a/src/Std/Data/ExtHashSet/Basic.lean +++ b/src/Std/Data/ExtHashSet/Basic.lean @@ -204,20 +204,16 @@ def union [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashSet α) : ExtHas instance [EquivBEq α] [LawfulHashable α] : Union (ExtHashSet α) := ⟨union⟩ -@[inline, inherit_doc ExtHashMap.beq] -def beq [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashSet α) : Bool := ExtDHashMap.Const.beq m₁.inner.inner m₂.inner.inner +instance [EquivBEq α] [LawfulHashable α] : BEq (ExtHashSet α) where + beq m₁ m₂ := ExtDHashMap.Const.beq m₁.inner.inner m₂.inner.inner -instance [LawfulBEq α] : BEq (ExtHashSet α) := ⟨beq⟩ - -instance [LawfulBEq α] : ReflBEq (ExtHashSet α) where - rfl {a} := by - have ⟨a⟩ := a - exact ExtDHashMap.Const.beq_of_eq _ _ rfl +instance [EquivBEq α] [LawfulHashable α] : ReflBEq (ExtHashSet α) where + rfl := ExtDHashMap.Const.beq_of_eq _ _ rfl instance [LawfulBEq α] : LawfulBEq (ExtHashSet α) where eq_of_beq {a} {b} hyp := by - have ⟨⟨a⟩⟩ := a - have ⟨⟨b⟩⟩ := b + have ⟨⟨_⟩⟩ := a + have ⟨⟨_⟩⟩ := b simp only [mk.injEq, ExtHashMap.mk.injEq] at |- hyp exact ExtDHashMap.Const.eq_of_beq _ _ hyp From 06c5d1dbad1822478025e859d9509c561703399a Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 5 Dec 2025 15:31:04 +0000 Subject: [PATCH 59/72] One more round of cleanup --- src/Std/Data/DHashMap/RawLemmas.lean | 2 +- src/Std/Data/ExtHashMap/Basic.lean | 4 ++-- src/Std/Data/HashMap/RawLemmas.lean | 2 +- src/Std/Data/HashSet/Lemmas.lean | 2 +- src/Std/Data/HashSet/RawLemmas.lean | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index 31212ae069e4..c2d489915a88 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -3782,7 +3782,7 @@ end BEq section variable {β : Type v} {m₁ m₂ : Raw α (fun _ => β)} -theorem Const.Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := by +theorem Const.Equiv.beq [EquivBEq α] [LawfulHashable α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := by simp_to_raw intro h exact Raw₀.Const.Equiv.beq h₁ h₂ h diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index f9fef7d90c59..7c6765203a20 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -258,8 +258,8 @@ instance [EquivBEq α] [LawfulHashable α] [BEq β] [ReflBEq β] : ReflBEq (ExtH instance [LawfulBEq α] [BEq β] [LawfulBEq β] : LawfulBEq (ExtHashMap α β) where eq_of_beq {a} {b} hyp := by - have ⟨a⟩ := a - have ⟨b⟩ := b + have ⟨_⟩ := a + have ⟨_⟩ := b simp only [mk.injEq] at |- hyp exact ExtDHashMap.Const.eq_of_beq _ _ hyp diff --git a/src/Std/Data/HashMap/RawLemmas.lean b/src/Std/Data/HashMap/RawLemmas.lean index 09c10f821269..4d0a2d1dc295 100644 --- a/src/Std/Data/HashMap/RawLemmas.lean +++ b/src/Std/Data/HashMap/RawLemmas.lean @@ -1311,7 +1311,7 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] (h : m.W section variable {β : Type v} {m₁ m₂ : Raw α β} -theorem Equiv.beq [LawfulHashable α] [EquivBEq α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → m₁ == m₂ := +theorem Equiv.beq [EquivBEq α] [LawfulHashable α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → m₁ == m₂ := fun hyp => DHashMap.Raw.Const.Equiv.beq h₁.1 h₂.1 hyp.1 theorem equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := diff --git a/src/Std/Data/HashSet/Lemmas.lean b/src/Std/Data/HashSet/Lemmas.lean index 0779a90f3fc8..321e24f4170f 100644 --- a/src/Std/Data/HashSet/Lemmas.lean +++ b/src/Std/Data/HashSet/Lemmas.lean @@ -785,7 +785,7 @@ end section variable {m₁ m₂ : HashSet α} -theorem Equiv.beq [LawfulHashable α] [EquivBEq α] (h : m₁ ~m m₂) : m₁ == m₂ := +theorem Equiv.beq [EquivBEq α] [LawfulHashable α] (h : m₁ ~m m₂) : m₁ == m₂ := HashMap.Equiv.beq h.1 theorem equiv_of_beq [LawfulBEq α] (h : m₁ == m₂) : m₁ ~m m₂ := diff --git a/src/Std/Data/HashSet/RawLemmas.lean b/src/Std/Data/HashSet/RawLemmas.lean index 70ad87f76b2f..8a615f02a69d 100644 --- a/src/Std/Data/HashSet/RawLemmas.lean +++ b/src/Std/Data/HashSet/RawLemmas.lean @@ -817,7 +817,7 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] (h : m.W section variable {m₁ m₂ : Raw α} -theorem Equiv.beq [LawfulHashable α] [EquivBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := +theorem Equiv.beq [EquivBEq α] [LawfulHashable α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := fun hyp => HashMap.Raw.Equiv.beq h₁.1 h₂.1 hyp.1 theorem equiv_of_beq [LawfulBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := From 4afd1910e54f7aa377ac21858fc4e51f861b63f7 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 5 Dec 2025 15:59:10 +0000 Subject: [PATCH 60/72] Further cleanup --- src/Std/Data/DHashMap/DecidableEquiv.lean | 3 ++- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 3 +-- src/Std/Data/ExtDHashMap/Basic.lean | 2 +- src/Std/Data/ExtHashMap/Basic.lean | 2 +- src/Std/Data/ExtHashSet/Basic.lean | 2 +- src/Std/Data/HashMap/DecidableEquiv.lean | 2 +- src/Std/Data/HashMap/RawDecidableEquiv.lean | 2 +- src/Std/Data/HashSet/DecidableEquiv.lean | 2 +- src/Std/Data/HashSet/RawDecidableEquiv.lean | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Std/Data/DHashMap/DecidableEquiv.lean b/src/Std/Data/DHashMap/DecidableEquiv.lean index 524daa8d6adb..fe56b1cf67a7 100644 --- a/src/Std/Data/DHashMap/DecidableEquiv.lean +++ b/src/Std/Data/DHashMap/DecidableEquiv.lean @@ -18,6 +18,7 @@ open Std.DHashMap.Internal namespace Std.DHashMap -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| Raw₀.decidableEquiv ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2 +instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := + letI : Decidable (m₁.1.Equiv m₂.1) := Raw₀.decidableEquiv ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.DHashMap diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index f652e069ffec..31f3963320b9 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -5140,8 +5140,7 @@ end Raw₀ namespace Raw₀ /-- Internal implementation detail -/ -def decidableEquiv [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] - (m₁ m₂ : Raw₀ α β) (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : Decidable (m₁.1.Equiv m₂.1) := by +def decidableEquiv [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : Raw₀ α β) (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : Decidable (m₁.1.Equiv m₂.1) := by apply decidable_of_iff (Raw₀.beq m₁ m₂ = true) constructor · apply Raw₀.equiv_of_beq h₁ h₂ diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index f6946fcaf492..13ed7dc8440f 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -372,7 +372,7 @@ instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : LawfulBE eq_of_beq {m₁} {m₂} := m₁.inductionOn₂ m₂ fun _ _ hyp => sound <| DHashMap.equiv_of_beq hyp instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] : DecidableEq (ExtDHashMap α β) := - fun m₁ m₂ => decidable_of_iff (m₁ == m₂) ⟨by simp, by simp⟩ + fun _ _ => decidable_of_iff _ beq_iff_eq namespace Const diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index 8e8420294bbc..5bf37fa481cf 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -264,7 +264,7 @@ instance [LawfulBEq α] [BEq β] [LawfulBEq β] : LawfulBEq (ExtHashMap α β) w exact ExtDHashMap.Const.eq_of_beq _ _ hyp instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] : DecidableEq (ExtDHashMap α β) := - fun m₁ m₂ => decidable_of_iff (m₁ == m₂) ⟨by simp, by simp⟩ + fun _ _ => decidable_of_iff _ beq_iff_eq @[inline, inherit_doc ExtDHashMap.inter] def inter [EquivBEq α] [LawfulHashable α] (m₁ m₂ : ExtHashMap α β) : ExtHashMap α β := ⟨ExtDHashMap.inter m₁.inner m₂.inner⟩ diff --git a/src/Std/Data/ExtHashSet/Basic.lean b/src/Std/Data/ExtHashSet/Basic.lean index b2a17a9dbab8..42e3e63a17c2 100644 --- a/src/Std/Data/ExtHashSet/Basic.lean +++ b/src/Std/Data/ExtHashSet/Basic.lean @@ -218,7 +218,7 @@ instance [LawfulBEq α] : LawfulBEq (ExtHashSet α) where exact ExtDHashMap.Const.eq_of_beq _ _ hyp instance {α : Type u} [DecidableEq α] [Hashable α] : DecidableEq (ExtHashSet α) := - fun m₁ m₂ => decidable_of_iff (m₁ == m₂) ⟨by simp, by simp⟩ + fun _ _ => decidable_of_iff _ beq_iff_eq /-- Computes the intersection of the given hash sets. diff --git a/src/Std/Data/HashMap/DecidableEquiv.lean b/src/Std/Data/HashMap/DecidableEquiv.lean index f6107eaed75c..a3149244d3c7 100644 --- a/src/Std/Data/HashMap/DecidableEquiv.lean +++ b/src/Std/Data/HashMap/DecidableEquiv.lean @@ -18,6 +18,6 @@ public section namespace Std.HashMap instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] (m₁ m₂ : HashMap α β) : Decidable (m₁ ~m m₂) := - @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| DHashMap.instDecidableEquivOfDecidableEq m₁.inner m₂.inner + decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.HashMap diff --git a/src/Std/Data/HashMap/RawDecidableEquiv.lean b/src/Std/Data/HashMap/RawDecidableEquiv.lean index 9537406810d7..7bc2f66f5fed 100644 --- a/src/Std/Data/HashMap/RawDecidableEquiv.lean +++ b/src/Std/Data/HashMap/RawDecidableEquiv.lean @@ -18,6 +18,6 @@ public section namespace Std.HashMap.Raw instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| DHashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out + letI : Decidable (m₁.1.Equiv m₂.1) := DHashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.HashMap.Raw diff --git a/src/Std/Data/HashSet/DecidableEquiv.lean b/src/Std/Data/HashSet/DecidableEquiv.lean index e85c7212094b..8baa49a051f2 100644 --- a/src/Std/Data/HashSet/DecidableEquiv.lean +++ b/src/Std/Data/HashSet/DecidableEquiv.lean @@ -18,6 +18,6 @@ public section namespace Std.HashSet instance {α : Type u} [DecidableEq α] [Hashable α] (m₁ m₂ : HashSet α) : Decidable (m₁ ~m m₂) := - @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| HashMap.instDecidableEquivOfDecidableEq m₁.inner m₂.inner + decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.HashSet diff --git a/src/Std/Data/HashSet/RawDecidableEquiv.lean b/src/Std/Data/HashSet/RawDecidableEquiv.lean index 3536734ce5aa..d0531ecd5b3b 100644 --- a/src/Std/Data/HashSet/RawDecidableEquiv.lean +++ b/src/Std/Data/HashSet/RawDecidableEquiv.lean @@ -18,6 +18,6 @@ public section namespace Std.HashSet.Raw instance {α : Type u} [DecidableEq α] [Hashable α] {m₁ m₂ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - @decidable_of_iff _ _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ <| HashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out + letI : Decidable (m₁.1.Equiv m₂.1) := HashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.HashSet.Raw From ea94efbb0fc4b8b03d84b85b95351186e112d578 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 5 Dec 2025 16:01:27 +0000 Subject: [PATCH 61/72] Fix whitespace --- src/Std/Data/ExtDHashMap/Basic.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index 3f4a21fd1f48..7c4909918571 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -374,6 +374,7 @@ instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : LawfulBE namespace Const variable {β : Type v} + @[inline, inherit_doc DHashMap.beq] def beq [EquivBEq α] [LawfulHashable α] [BEq β] (m₁ m₂ : ExtDHashMap α fun _ => β) : Bool := lift₂ (fun x y : DHashMap α fun _ => β => DHashMap.Const.beq x y) (fun _ _ _ _ => DHashMap.Const.Equiv.beq_congr) m₁ m₂ From 085187c3601ad6a4f9aea9f78bfce33695baf274 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 5 Dec 2025 16:05:29 +0000 Subject: [PATCH 62/72] chore: change `letI` to `let` --- src/Std/Data/DHashMap/DecidableEquiv.lean | 2 +- src/Std/Data/HashMap/RawDecidableEquiv.lean | 2 +- src/Std/Data/HashSet/RawDecidableEquiv.lean | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Std/Data/DHashMap/DecidableEquiv.lean b/src/Std/Data/DHashMap/DecidableEquiv.lean index fe56b1cf67a7..496d0d5b43c6 100644 --- a/src/Std/Data/DHashMap/DecidableEquiv.lean +++ b/src/Std/Data/DHashMap/DecidableEquiv.lean @@ -19,6 +19,6 @@ open Std.DHashMap.Internal namespace Std.DHashMap instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := - letI : Decidable (m₁.1.Equiv m₂.1) := Raw₀.decidableEquiv ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ + let : Decidable (m₁.1.Equiv m₂.1) := Raw₀.decidableEquiv ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.DHashMap diff --git a/src/Std/Data/HashMap/RawDecidableEquiv.lean b/src/Std/Data/HashMap/RawDecidableEquiv.lean index 7bc2f66f5fed..815bfafcd6f2 100644 --- a/src/Std/Data/HashMap/RawDecidableEquiv.lean +++ b/src/Std/Data/HashMap/RawDecidableEquiv.lean @@ -18,6 +18,6 @@ public section namespace Std.HashMap.Raw instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - letI : Decidable (m₁.1.Equiv m₂.1) := DHashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ + let : Decidable (m₁.1.Equiv m₂.1) := DHashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.HashMap.Raw diff --git a/src/Std/Data/HashSet/RawDecidableEquiv.lean b/src/Std/Data/HashSet/RawDecidableEquiv.lean index d0531ecd5b3b..2e962528fad5 100644 --- a/src/Std/Data/HashSet/RawDecidableEquiv.lean +++ b/src/Std/Data/HashSet/RawDecidableEquiv.lean @@ -18,6 +18,6 @@ public section namespace Std.HashSet.Raw instance {α : Type u} [DecidableEq α] [Hashable α] {m₁ m₂ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - letI : Decidable (m₁.1.Equiv m₂.1) := HashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ + let : Decidable (m₁.1.Equiv m₂.1) := HashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.HashSet.Raw From 3079fa6b1495e6fa34765b7d63d29299b30eb877 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 5 Dec 2025 17:04:30 +0000 Subject: [PATCH 63/72] Further cleanup --- src/Std/Data/DHashMap/Lemmas.lean | 8 +++---- src/Std/Data/DHashMap/RawLemmas.lean | 33 +++++++++++----------------- src/Std/Data/HashMap/Lemmas.lean | 4 ++-- src/Std/Data/HashMap/RawLemmas.lean | 13 +++++------ src/Std/Data/HashSet/Lemmas.lean | 4 ++-- src/Std/Data/HashSet/RawLemmas.lean | 12 +++++----- 6 files changed, 33 insertions(+), 41 deletions(-) diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index 80a288f27208..cc675aa533c3 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -1847,8 +1847,8 @@ theorem Equiv.beq [∀ k, ReflBEq (β k)] (h : m₁ ~m m₂) : m₁ == m₂ := theorem equiv_of_beq [∀ k, LawfulBEq (β k)] (h : m₁ == m₂) : m₁ ~m m₂ := ⟨Raw₀.equiv_of_beq m₁.2 m₂.2 h⟩ -theorem Equiv.beq_congr {m₃ m₄ : DHashMap α β} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := - fun h1 h2 => Raw₀.Equiv.beq_congr m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 +theorem Equiv.beq_congr {m₃ m₄ : DHashMap α β} (w₁ : m₁ ~m m₃) (w₂ : m₂ ~m m₄) : (m₁ == m₂) = (m₃ == m₄) := + Raw₀.Equiv.beq_congr m₁.2 m₂.2 m₃.2 m₄.2 w₁.1 w₂.1 end BEq @@ -1861,8 +1861,8 @@ theorem Const.Equiv.beq [EquivBEq α] [LawfulHashable α] [ReflBEq β] (h : m₁ theorem Const.equiv_of_beq [LawfulBEq α] [LawfulBEq β] (h : Const.beq m₁ m₂) : m₁ ~m m₂ := ⟨Raw₀.Const.equiv_of_beq m₁.2 m₂.2 h⟩ -theorem Const.Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : DHashMap α (fun _ => β)} : m₁ ~m m₃ → m₂ ~m m₄ → Const.beq m₁ m₂ = Const.beq m₃ m₄ := - fun h1 h2 => Raw₀.Const.Equiv.beq_congr m₁.2 m₂.2 m₃.2 m₄.2 h1.1 h2.1 +theorem Const.Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : DHashMap α (fun _ => β)} (w₁ : m₁ ~m m₃) (w₂ : m₂ ~m m₄) : Const.beq m₁ m₂ = Const.beq m₃ m₄ := + Raw₀.Const.Equiv.beq_congr m₁.2 m₂.2 m₃.2 m₄.2 w₁.1 w₂.1 end diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index c2d489915a88..2fa66c130486 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -3762,39 +3762,32 @@ open Internal.Raw Internal.Raw₀ section BEq variable {m₁ m₂ : Raw α β} [LawfulBEq α] [∀ k, BEq (β k)] -theorem Equiv.beq [∀ k, ReflBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → m₁ == m₂ := by +theorem Equiv.beq [∀ k, ReflBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : m₁ ~m m₂) : m₁ == m₂ := by simp only [BEq.beq] - simp_to_raw - intro h - exact Raw₀.Equiv.beq h₁ h₂ h + simp_to_raw using Raw₀.Equiv.beq -theorem equiv_of_beq [∀ k, LawfulBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) : beq m₁ m₂ = true → m₁ ~m m₂ := by +theorem equiv_of_beq [∀ k, LawfulBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : beq m₁ m₂ = true) : m₁ ~m m₂ := by + revert h simp_to_raw using Raw₀.equiv_of_beq -theorem Equiv.beq_congr {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : - m₁ ~m m₃ → m₂ ~m m₄ → Raw.beq m₁ m₂ = Raw.beq m₃ m₄ := by - simp_to_raw - intro w1 w2 - exact Raw₀.Equiv.beq_congr h₁ h₂ h₃ h₄ w1 w2 +theorem Equiv.beq_congr {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) (w₁ : m₁ ~m m₃) (w₂ : m₂ ~m m₄) : Raw.beq m₁ m₂ = Raw.beq m₃ m₄ := by + simp_to_raw using Raw₀.Equiv.beq_congr end BEq section + variable {β : Type v} {m₁ m₂ : Raw α (fun _ => β)} -theorem Const.Equiv.beq [EquivBEq α] [LawfulHashable α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := by - simp_to_raw - intro h - exact Raw₀.Const.Equiv.beq h₁ h₂ h +theorem Const.Equiv.beq [EquivBEq α] [LawfulHashable α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : m₁ ~m m₂) : beq m₁ m₂ := by + simp_to_raw using Raw₀.Const.Equiv.beq -theorem Const.equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : beq m₁ m₂ = true → m₁ ~m m₂ := by +theorem Const.equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : beq m₁ m₂ = true ) : m₁ ~m m₂ := by + revert h simp_to_raw using Raw₀.Const.equiv_of_beq -theorem Const.Equiv.beq_congr [EquivBEq α] [LawfulHashable α] [BEq β] {m₃ m₄ : Raw α (fun _ => β)} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : - m₁ ~m m₃ → m₂ ~m m₄ → Raw.Const.beq m₁ m₂ = Raw.Const.beq m₃ m₄ := by - simp_to_raw - intro w1 w2 - exact Raw₀.Const.Equiv.beq_congr h₁ h₂ h₃ h₄ w1 w2 +theorem Const.Equiv.beq_congr [EquivBEq α] [LawfulHashable α] [BEq β] {m₃ m₄ : Raw α (fun _ => β)} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) (w₁ : m₁ ~m m₃) (w₂ : m₂ ~m m₄) : Raw.Const.beq m₁ m₂ = Raw.Const.beq m₃ m₄ := by + simp_to_raw using Raw₀.Const.Equiv.beq_congr end diff --git a/src/Std/Data/HashMap/Lemmas.lean b/src/Std/Data/HashMap/Lemmas.lean index 09ffbc320c47..ca9d9df352fa 100644 --- a/src/Std/Data/HashMap/Lemmas.lean +++ b/src/Std/Data/HashMap/Lemmas.lean @@ -1355,8 +1355,8 @@ theorem Equiv.beq [EquivBEq α] [LawfulHashable α] [ReflBEq β] (h : m₁ ~m m theorem equiv_of_beq [LawfulBEq α] [LawfulBEq β] (h : m₁ == m₂) : m₁ ~m m₂ := ⟨DHashMap.Const.equiv_of_beq h⟩ -theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : HashMap α β} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := fun h1 h2 => - DHashMap.Const.Equiv.beq_congr h1.1 h2.1 +theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : HashMap α β} (w₁ : m₁ ~m m₃) (w₂ : m₂ ~m m₄) : (m₁ == m₂) = (m₃ == m₄) := + DHashMap.Const.Equiv.beq_congr w₁.1 w₂.1 end diff --git a/src/Std/Data/HashMap/RawLemmas.lean b/src/Std/Data/HashMap/RawLemmas.lean index 4d0a2d1dc295..8e6316db9d97 100644 --- a/src/Std/Data/HashMap/RawLemmas.lean +++ b/src/Std/Data/HashMap/RawLemmas.lean @@ -1311,15 +1311,14 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] (h : m.W section variable {β : Type v} {m₁ m₂ : Raw α β} -theorem Equiv.beq [EquivBEq α] [LawfulHashable α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → m₁ == m₂ := - fun hyp => DHashMap.Raw.Const.Equiv.beq h₁.1 h₂.1 hyp.1 +theorem Equiv.beq [EquivBEq α] [LawfulHashable α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : m₁ ~m m₂) : m₁ == m₂ := + DHashMap.Raw.Const.Equiv.beq h₁.1 h₂.1 h.1 -theorem equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := - fun hyp => ⟨DHashMap.Raw.Const.equiv_of_beq h₁.1 h₂.1 hyp⟩ +theorem equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : m₁ == m₂) : m₁ ~m m₂ := + ⟨DHashMap.Raw.Const.equiv_of_beq h₁.1 h₂.1 h⟩ -theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] [BEq β] {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : - m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := - fun hyp1 hyp2 => DHashMap.Raw.Const.Equiv.beq_congr h₁.1 h₂.1 h₃.1 h₄.1 hyp1.1 hyp2.1 +theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] [BEq β] {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) (w₁ : m₁ ~m m₃) (w₂ : m₂ ~m m₄) : (m₁ == m₂) = (m₃ == m₄) := + DHashMap.Raw.Const.Equiv.beq_congr h₁.1 h₂.1 h₃.1 h₄.1 w₁.1 w₂.1 end diff --git a/src/Std/Data/HashSet/Lemmas.lean b/src/Std/Data/HashSet/Lemmas.lean index 321e24f4170f..1a24d6f9a2ee 100644 --- a/src/Std/Data/HashSet/Lemmas.lean +++ b/src/Std/Data/HashSet/Lemmas.lean @@ -791,8 +791,8 @@ theorem Equiv.beq [EquivBEq α] [LawfulHashable α] (h : m₁ ~m m₂) : m₁ == theorem equiv_of_beq [LawfulBEq α] (h : m₁ == m₂) : m₁ ~m m₂ := ⟨HashMap.equiv_of_beq h⟩ -theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : HashSet α} : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := - fun h1 h2 => HashMap.Equiv.beq_congr h1.1 h2.1 +theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : HashSet α} (h₁ : m₁ ~m m₃) (h₂ : m₂ ~m m₄) : (m₁ == m₂) = (m₃ == m₄) := + HashMap.Equiv.beq_congr h₁.1 h₂.1 end diff --git a/src/Std/Data/HashSet/RawLemmas.lean b/src/Std/Data/HashSet/RawLemmas.lean index 8a615f02a69d..8c0a8f01b0d7 100644 --- a/src/Std/Data/HashSet/RawLemmas.lean +++ b/src/Std/Data/HashSet/RawLemmas.lean @@ -817,14 +817,14 @@ theorem isEmpty_of_isEmpty_insertMany [EquivBEq α] [LawfulHashable α] (h : m.W section variable {m₁ m₂ : Raw α} -theorem Equiv.beq [EquivBEq α] [LawfulHashable α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ ~m m₂ → beq m₁ m₂ := - fun hyp => HashMap.Raw.Equiv.beq h₁.1 h₂.1 hyp.1 +theorem Equiv.beq [EquivBEq α] [LawfulHashable α] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : m₁ ~m m₂) : beq m₁ m₂ := + HashMap.Raw.Equiv.beq h₁.1 h₂.1 h.1 -theorem equiv_of_beq [LawfulBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁ == m₂ → m₁ ~m m₂ := - fun hyp => ⟨HashMap.Raw.equiv_of_beq h₁.1 h₂.1 hyp⟩ +theorem equiv_of_beq [LawfulBEq α] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : m₁ == m₂) : m₁ ~m m₂ := + ⟨HashMap.Raw.equiv_of_beq h₁.1 h₂.1 h⟩ -theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) : m₁ ~m m₃ → m₂ ~m m₄ → (m₁ == m₂) = (m₃ == m₄) := - fun hyp1 hyp2 => HashMap.Raw.Equiv.beq_congr h₁.1 h₂.1 h₃.1 h₄.1 hyp1.1 hyp2.1 +theorem Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) (w₁ : m₁ ~m m₃) (w₂ : m₂ ~m m₄) : (m₁ == m₂) = (m₃ == m₄) := + HashMap.Raw.Equiv.beq_congr h₁.1 h₂.1 h₃.1 h₄.1 w₁.1 w₂.1 end From f353aeae4d252b458216c6a740aff4ef6685e04d Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 5 Dec 2025 18:51:50 +0000 Subject: [PATCH 64/72] Proof golf --- src/Std/Data/Internal/List/Associative.lean | 119 +++++++------------- 1 file changed, 41 insertions(+), 78 deletions(-) diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 3fda1030af1d..635dc5a8bfec 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -7638,7 +7638,7 @@ theorem beqModel_eq_true_of_perm [BEq α] [LawfulBEq α] [LawfulBEq α] [∀ k, rw [beqModel, if_neg (by simpa using hyp.length_eq)] simp only [List.all_eq_true] intro ⟨k,v⟩ mem - have hv := @getValueCast_of_mem α β _ _ l₁ ⟨k,v⟩ mem + have hv := getValueCast_of_mem mem have hc := containsKey_of_mem mem apply beq_of_eq simp only at |- hc hv @@ -7662,90 +7662,56 @@ theorem Const.beqModel_eq_true_of_perm {β : Type v} [BEq α] [EquivBEq α] [BEq · exact hl₁ · exact hc -theorem perm_of_beqModel [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : - beqModel l₁ l₂ → l₁.Perm l₂ := by - rw [beqModel] - split - case isTrue => intro; contradiction - case isFalse he => - simp only [ne_eq, Decidable.not_not] at he - simp only [List.all_eq_true, beq_iff_eq] - intro hyp - apply getValueCast?_ext hl₁ hl₂ - intro a - have hyp2 : ∀ (a : α) (h : containsKey a l₁), (getValueCast? a l₂ == getValueCast? a l₁) = true := by +theorem perm_of_beqModel [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : beqModel l₁ l₂ → l₁.Perm l₂ := by + simp only [beqModel, ne_eq, ite_not, Bool.if_false_right, Bool.and_eq_true, decide_eq_true_eq, + List.all_eq_true, beq_iff_eq, and_imp] + intro he hyp + apply getValueCast?_ext hl₁ hl₂ + intro a + have hyp2 : ∀ (a : α) (h : containsKey a l₁), (getValueCast? a l₂ == getValueCast? a l₁) = true := by intro a mem rw [getValueCast?_eq_some_getValueCast mem] apply beq_of_eq - specialize hyp ⟨a, getValueCast a l₁ mem⟩ - specialize hyp (by apply List.getValueCast_mem) - simp only at hyp - rw [hyp] - by_cases hc₁ : containsKey a l₁ + specialize hyp ⟨a, getValueCast a l₁ mem⟩ (List.getValueCast_mem mem) + simpa using hyp + by_cases hc₁ : containsKey a l₁ + case pos => + exact eq_of_beq <| BEq.symm <| hyp2 _ hc₁ + case neg => + rw [Bool.not_eq_true] at hc₁ + by_cases hc₂ : containsKey a l₂ case pos => - apply eq_of_beq - apply BEq.symm - apply hyp2 - exact hc₁ + suffices (∀ (a : α), containsKey a l₁ = true → containsKey a l₂ = true) by + rw [containsKey_of_length_eq hl₁ hl₂ he.symm this a hc₂] at hc₁ + contradiction + intro k' mem + apply List.containsKey_of_getValueCast?_eq_some + simpa [getValueCast?_eq_some_getValueCast mem] using eq_of_beq <| hyp2 k' mem case neg => - rw [Bool.not_eq_true] at hc₁ - by_cases hc₂ : containsKey a l₂ - case pos => - suffices (∀ (a : α), containsKey a l₁ = true → containsKey a l₂ = true) by - rw [@containsKey_of_length_eq α β _ _ l₁ l₂ hl₁ hl₂ he.symm this a hc₂] at hc₁ - contradiction - intro k' mem - have := eq_of_beq <| hyp2 k' mem - rw [getValueCast?_eq_some_getValueCast mem] at this - apply List.containsKey_of_getValueCast?_eq_some - exact this - case neg => - rw [Bool.not_eq_true] at hc₂ - rw [getValueCast?_eq_none hc₁, getValueCast?_eq_none hc₂] + rw [Bool.not_eq_true] at hc₂ + rw [getValueCast?_eq_none hc₁, getValueCast?_eq_none hc₂] theorem beqModel_congr [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] {l₁ l₂ l₃ l₄ : List ((a : α) × β a)} (hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by - rw [beqModel] - split - case isTrue h => - rw [ne_eq] at h - rw [beqModel] - simp only [ne_eq, ite_not, Bool.if_false_right, Bool.false_eq, Bool.and_eq_false_imp, - decide_eq_true_eq] - intro hyp - rw [Perm.length_eq p₁, Perm.length_eq p₂] at h - contradiction - case isFalse h => - rw [beqModel] - rw [Perm.length_eq p₁, Perm.length_eq p₂] at h - simp only [h, ↓reduceIte] - have : fun (x : (a : α) × β a) => getValueCast? x.fst l₂ == some x.snd = fun x => getValueCast? x.fst l₄ == some x.snd := by - ext x - rw [getValueCast?_of_perm hl p₂] - rw [this] - apply List.Perm.all_eq p₁ + simp only [beqModel, ne_eq, ite_not, Bool.if_false_right, Perm.length_eq p₁, Perm.length_eq p₂] + suffices h : (l₁.all fun x => getValueCast? x.fst l₂ == some x.snd) = (l₃.all fun x => getValueCast? x.fst l₄ == some x.snd) by simp [h] + conv => + lhs + rhs + ext x + rw [getValueCast?_of_perm hl p₂] + apply List.Perm.all_eq p₁ theorem Const.beqModel_congr {β : Type v} [BEq α] [EquivBEq α] [BEq β] {l₁ l₂ l₃ l₄ : List ((_ : α) × β)} (hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by - rw [beqModel] - split - case isTrue h => - rw [ne_eq] at h - rw [beqModel] - simp only [ne_eq, ite_not, Bool.if_false_right, Bool.false_eq, Bool.and_eq_false_imp, - decide_eq_true_eq] - intro hyp - rw [Perm.length_eq p₁, Perm.length_eq p₂] at h - contradiction - case isFalse h => - rw [beqModel] - rw [Perm.length_eq p₁, Perm.length_eq p₂] at h - simp only [h, ↓reduceIte] - have : fun (x : (_ : α) × β) => getValue? x.fst l₂ == some x.snd = fun x => getValue? x.fst l₄ == some x.snd := by - ext x - rw [getValue?_of_perm hl p₂] - rw [this] - apply List.Perm.all_eq p₁ + simp only [beqModel, ne_eq, ite_not, Bool.if_false_right, Perm.length_eq p₁, Perm.length_eq p₂] + suffices h : (l₁.all fun x => getValue? x.fst l₂ == some x.snd) = (l₃.all fun x => getValue? x.fst l₄ == some x.snd) by simp [h] + conv => + lhs + rhs + ext x + rw [getValue?_of_perm hl p₂] + apply List.Perm.all_eq p₁ theorem beqModel_eq_constBeqModel {β : Type v} [BEq α] [LawfulBEq α] [BEq β] {l₁ l₂ : List ((_ : α) × β)} : beqModel l₁ l₂ = Const.beqModel l₁ l₂ := by rw [beqModel, Const.beqModel] @@ -7757,10 +7723,7 @@ theorem Const.perm_of_beqModel {β : Type v} [BEq α] [LawfulBEq α] [BEq β] [L beqModel l₁ l₂ → l₁.Perm l₂ := by rw [← beqModel_eq_constBeqModel] intro hyp - apply List.perm_of_beqModel - · exact hl₁ - · exact hl₂ - · exact hyp + apply List.perm_of_beqModel hl₁ hl₂ hyp namespace Const From fb951bf58b3d269b78f0c93ac78cdc9166443585 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 5 Dec 2025 20:29:12 +0000 Subject: [PATCH 65/72] Add names for instances --- src/Std/Data/DHashMap/RawDecidableEquiv.lean | 2 +- src/Std/Data/HashMap/RawDecidableEquiv.lean | 6 ++++-- src/Std/Data/HashSet/RawDecidableEquiv.lean | 7 +++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Std/Data/DHashMap/RawDecidableEquiv.lean b/src/Std/Data/DHashMap/RawDecidableEquiv.lean index 51a8f9874705..5c8c803ac8bb 100644 --- a/src/Std/Data/DHashMap/RawDecidableEquiv.lean +++ b/src/Std/Data/DHashMap/RawDecidableEquiv.lean @@ -18,7 +18,7 @@ open Std.DHashMap.Internal namespace Std.DHashMap.Raw -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := +instance instDecidableEquiv {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) := Raw₀.decidableEquiv ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ end Std.DHashMap.Raw diff --git a/src/Std/Data/HashMap/RawDecidableEquiv.lean b/src/Std/Data/HashMap/RawDecidableEquiv.lean index 815bfafcd6f2..4199d459ca63 100644 --- a/src/Std/Data/HashMap/RawDecidableEquiv.lean +++ b/src/Std/Data/HashMap/RawDecidableEquiv.lean @@ -15,9 +15,11 @@ public section # Decidable equivalence for `HashMap.Raw` -/ +open Std.DHashMap.Raw + namespace Std.HashMap.Raw -instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - let : Decidable (m₁.1.Equiv m₂.1) := DHashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ +instance instDecidableEquiv {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) := + let : Decidable (m₁.1 ~m m₂.1) := DHashMap.Raw.instDecidableEquiv h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.HashMap.Raw diff --git a/src/Std/Data/HashSet/RawDecidableEquiv.lean b/src/Std/Data/HashSet/RawDecidableEquiv.lean index 2e962528fad5..ae56aa137aa8 100644 --- a/src/Std/Data/HashSet/RawDecidableEquiv.lean +++ b/src/Std/Data/HashSet/RawDecidableEquiv.lean @@ -15,9 +15,12 @@ public section # Decidable equivalence for `HashSet.Raw` -/ + +open Std.HashMap.Raw + namespace Std.HashSet.Raw -instance {α : Type u} [DecidableEq α] [Hashable α] {m₁ m₂ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁.Equiv m₂) := - let : Decidable (m₁.1.Equiv m₂.1) := HashMap.Raw.instDecidableEquivOfDecidableEqOfWF h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ +instance instDecidableEquiv {α : Type u} [DecidableEq α] [Hashable α] {m₁ m₂ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) := + let : Decidable (m₁.1 ~m m₂.1) := HashMap.Raw.instDecidableEquiv h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.HashSet.Raw From 3074be8c87afab8481beecc9cbbc2c4dcc3385ae Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Mon, 8 Dec 2025 06:57:55 +0000 Subject: [PATCH 66/72] Add `any_eq` --- src/Init/Data/List/Perm.lean | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Init/Data/List/Perm.lean b/src/Init/Data/List/Perm.lean index f67d05975514..bc8e3d9db3bd 100644 --- a/src/Init/Data/List/Perm.lean +++ b/src/Init/Data/List/Perm.lean @@ -602,13 +602,10 @@ theorem sum_nat {l₁ l₂ : List Nat} (h : l₁ ~ l₂) : l₁.sum = l₂.sum : | trans _ _ ih₁ ih₂ => simp [ih₁, ih₂] theorem all_eq {l₁ l₂ : List α} {f : α → Bool} (hp : l₁.Perm l₂) : l₁.all f = l₂.all f := by - rw [Bool.eq_iff_iff, Bool.eq_iff_iff, List.all_eq_true, List.all_eq_true] - simp only [iff_true] - constructor - · intro hyp e mem - exact hyp e (@Perm.mem_iff _ e l₁ l₂ hp |>.2 mem) - · intro hyp e mem - exact hyp e (@Perm.mem_iff _ e l₂ l₁ hp.symm |>.2 mem) + rw [Bool.eq_iff_iff]; simp [hp.mem_iff] + +theorem any_eq {l₁ l₂ : List α} {f : α → Bool} (hp : l₁.Perm l₂) : l₁.any f = l₂.any f := by + rw [Bool.eq_iff_iff]; simp [hp.mem_iff] grind_pattern Perm.sum_nat => l₁ ~ l₂, l₁.sum grind_pattern Perm.sum_nat => l₁ ~ l₂, l₂.sum From 02434df82042a4c83ef0fc38be82200ff74268f1 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Mon, 8 Dec 2025 07:09:26 +0000 Subject: [PATCH 67/72] Minor cleanup --- src/Std/Data/DHashMap/Internal/Raw.lean | 4 ++-- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Std/Data/DHashMap/Internal/Raw.lean b/src/Std/Data/DHashMap/Internal/Raw.lean index e973b1e5d254..254694ed065f 100644 --- a/src/Std/Data/DHashMap/Internal/Raw.lean +++ b/src/Std/Data/DHashMap/Internal/Raw.lean @@ -159,9 +159,9 @@ theorem beq_eq [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] {m₁ m simp [Raw.beq, h₁.size_buckets_pos, h₂.size_buckets_pos] theorem Const.beq_eq {β : Type v} [BEq α] [Hashable α] [BEq β] {m₁ m₂ : Raw α (fun _ => β)} (h₁ : m₁.WF) (h₂ : m₂.WF) : - Raw.Const.beq m₁ m₂ = Raw₀.Const.beq ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ := by + Raw.Const.beq m₁ m₂ = Raw₀.Const.beq ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ := by simp [Raw.Const.beq, h₁.size_buckets_pos, h₂.size_buckets_pos] - + theorem diff_eq [BEq α] [Hashable α] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : m₁.diff m₂ = Raw₀.diff ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ := by simp [Raw.diff, h₁.size_buckets_pos, h₂.size_buckets_pos] diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 8bc58a559ea4..db6918675d0a 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -2613,6 +2613,7 @@ theorem Const.equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.v theorem Const.Equiv.beq_congr [EquivBEq α] [LawfulHashable α] {m₃ m₄ : Raw₀ α (fun _ => β)} [BEq β] (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) (h₃ : m₃.val.WF) (h₄ : m₄.val.WF) : m₁.1.Equiv m₃.1 → m₂.1.Equiv m₄.1 → Const.beq m₁ m₂ = Const.beq m₃ m₄ := by simp_to_model using List.Const.beqModel_congr + end section Union From a269546d8de8cca8698f7f3d1d790d11a73b2bc1 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Mon, 8 Dec 2025 07:17:46 +0000 Subject: [PATCH 68/72] chore: proof golf --- src/Std/Data/DHashMap/Internal/Defs.lean | 1 + src/Std/Data/Internal/List/Associative.lean | 19 +++---------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/Std/Data/DHashMap/Internal/Defs.lean b/src/Std/Data/DHashMap/Internal/Defs.lean index d7c6738f5a60..c31d0fe686e5 100644 --- a/src/Std/Data/DHashMap/Internal/Defs.lean +++ b/src/Std/Data/DHashMap/Internal/Defs.lean @@ -498,6 +498,7 @@ def beq [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] (m₁ m₂ : R @[inline] def diff [BEq α] [Hashable α] (m₁ m₂ : Raw₀ α β) : Raw₀ α β := if m₁.1.size ≤ m₂.1.size then m₁.filter (fun k _ => !m₂.contains k) else (eraseManyEntries m₁ m₂.1).1 + section variable {β : Type v} diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 635dc5a8bfec..219efb10c9c4 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -7695,29 +7695,16 @@ theorem beqModel_congr [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] {l₁ l₂ l (hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by simp only [beqModel, ne_eq, ite_not, Bool.if_false_right, Perm.length_eq p₁, Perm.length_eq p₂] suffices h : (l₁.all fun x => getValueCast? x.fst l₂ == some x.snd) = (l₃.all fun x => getValueCast? x.fst l₄ == some x.snd) by simp [h] - conv => - lhs - rhs - ext x - rw [getValueCast?_of_perm hl p₂] - apply List.Perm.all_eq p₁ + simp [getValueCast?_of_perm hl p₂, List.Perm.all_eq p₁] theorem Const.beqModel_congr {β : Type v} [BEq α] [EquivBEq α] [BEq β] {l₁ l₂ l₃ l₄ : List ((_ : α) × β)} (hl : DistinctKeys l₂) (p₁ : l₁.Perm l₃) (p₂ : l₂.Perm l₄) : beqModel l₁ l₂ = beqModel l₃ l₄ := by simp only [beqModel, ne_eq, ite_not, Bool.if_false_right, Perm.length_eq p₁, Perm.length_eq p₂] suffices h : (l₁.all fun x => getValue? x.fst l₂ == some x.snd) = (l₃.all fun x => getValue? x.fst l₄ == some x.snd) by simp [h] - conv => - lhs - rhs - ext x - rw [getValue?_of_perm hl p₂] - apply List.Perm.all_eq p₁ + simp [getValue?_of_perm hl p₂, List.Perm.all_eq p₁] theorem beqModel_eq_constBeqModel {β : Type v} [BEq α] [LawfulBEq α] [BEq β] {l₁ l₂ : List ((_ : α) × β)} : beqModel l₁ l₂ = Const.beqModel l₁ l₂ := by - rw [beqModel, Const.beqModel] - congr - ext x - rw [getValue?_eq_getValueCast?] + simp [beqModel, Const.beqModel, getValue?_eq_getValueCast?] theorem Const.perm_of_beqModel {β : Type v} [BEq α] [LawfulBEq α] [BEq β] [LawfulBEq β] {l₁ l₂ : List ((_ : α) × β)} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys l₂) : beqModel l₁ l₂ → l₁.Perm l₂ := by From 7e9771bc90fdfda88b5522a7965d77a3307cc7ee Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Mon, 8 Dec 2025 07:39:56 +0000 Subject: [PATCH 69/72] chore: cleanup --- src/Std/Data/DHashMap/DecidableEquiv.lean | 3 ++- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 7 ++----- src/Std/Data/DHashMap/Lemmas.lean | 1 - src/Std/Data/ExtHashMap/Basic.lean | 2 +- src/Std/Data/HashMap/Lemmas.lean | 1 - src/Std/Data/HashMap/RawDecidableEquiv.lean | 3 ++- src/Std/Data/HashMap/RawLemmas.lean | 1 - src/Std/Data/HashSet/Lemmas.lean | 1 - src/Std/Data/HashSet/RawDecidableEquiv.lean | 4 ++-- 9 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/Std/Data/DHashMap/DecidableEquiv.lean b/src/Std/Data/DHashMap/DecidableEquiv.lean index 496d0d5b43c6..64e0419828f8 100644 --- a/src/Std/Data/DHashMap/DecidableEquiv.lean +++ b/src/Std/Data/DHashMap/DecidableEquiv.lean @@ -19,6 +19,7 @@ open Std.DHashMap.Internal namespace Std.DHashMap instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := - let : Decidable (m₁.1.Equiv m₂.1) := Raw₀.decidableEquiv ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ + let : Decidable (m₁.1.Equiv m₂.1) := Raw₀.decidableEquiv ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2; + decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.DHashMap diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index c34c1b72cb7d..3ce132c8a833 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -5141,11 +5141,8 @@ end Raw₀ namespace Raw₀ /-- Internal implementation detail -/ -def decidableEquiv [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : Raw₀ α β) (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : Decidable (m₁.1.Equiv m₂.1) := by - apply decidable_of_iff (Raw₀.beq m₁ m₂ = true) - constructor - · apply Raw₀.equiv_of_beq h₁ h₂ - · apply Raw₀.Equiv.beq h₁ h₂ +def decidableEquiv [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : Raw₀ α β) (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : Decidable (m₁.1.Equiv m₂.1) := + decidable_of_iff _ ⟨Raw₀.equiv_of_beq h₁ h₂, Raw₀.Equiv.beq h₁ h₂⟩ end Raw₀ diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index 3ddd78a7f968..9ad57c0d94a8 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -5339,6 +5339,5 @@ theorem toList_map {m : DHashMap α fun _ => β} end Const end map - attribute [simp] contains_eq_false_iff_not_mem end Std.DHashMap diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index 5bf37fa481cf..1957ac130b4f 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -263,7 +263,7 @@ instance [LawfulBEq α] [BEq β] [LawfulBEq β] : LawfulBEq (ExtHashMap α β) w simp only [mk.injEq] at |- hyp exact ExtDHashMap.Const.eq_of_beq _ _ hyp -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] : DecidableEq (ExtDHashMap α β) := +instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] : DecidableEq (ExtHashMap α β) := fun _ _ => decidable_of_iff _ beq_iff_eq @[inline, inherit_doc ExtDHashMap.inter] diff --git a/src/Std/Data/HashMap/Lemmas.lean b/src/Std/Data/HashMap/Lemmas.lean index 58285a51d676..ca9d9df352fa 100644 --- a/src/Std/Data/HashMap/Lemmas.lean +++ b/src/Std/Data/HashMap/Lemmas.lean @@ -3492,6 +3492,5 @@ theorem getKeyD_map [EquivBEq α] [LawfulHashable α] DHashMap.getKeyD_map end map - attribute [simp] contains_eq_false_iff_not_mem end Std.HashMap diff --git a/src/Std/Data/HashMap/RawDecidableEquiv.lean b/src/Std/Data/HashMap/RawDecidableEquiv.lean index 4199d459ca63..cf8a667e87d3 100644 --- a/src/Std/Data/HashMap/RawDecidableEquiv.lean +++ b/src/Std/Data/HashMap/RawDecidableEquiv.lean @@ -20,6 +20,7 @@ open Std.DHashMap.Raw namespace Std.HashMap.Raw instance instDecidableEquiv {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) := - let : Decidable (m₁.1 ~m m₂.1) := DHashMap.Raw.instDecidableEquiv h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ + let : Decidable (m₁.1 ~m m₂.1) := DHashMap.Raw.instDecidableEquiv h₁.out h₂.out; + decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.HashMap.Raw diff --git a/src/Std/Data/HashMap/RawLemmas.lean b/src/Std/Data/HashMap/RawLemmas.lean index 195fadff6793..8e6316db9d97 100644 --- a/src/Std/Data/HashMap/RawLemmas.lean +++ b/src/Std/Data/HashMap/RawLemmas.lean @@ -3552,7 +3552,6 @@ theorem getD_map_of_getKey?_eq_some [EquivBEq α] [LawfulHashable α] DHashMap.Raw.Const.getD_map_of_getKey?_eq_some h.out h' end map - attribute [simp] contains_eq_false_iff_not_mem end Raw diff --git a/src/Std/Data/HashSet/Lemmas.lean b/src/Std/Data/HashSet/Lemmas.lean index b643649079a5..1a24d6f9a2ee 100644 --- a/src/Std/Data/HashSet/Lemmas.lean +++ b/src/Std/Data/HashSet/Lemmas.lean @@ -1535,6 +1535,5 @@ theorem getD_filter [EquivBEq α] [LawfulHashable α] HashMap.getKeyD_filter_key end filter - attribute [simp] contains_eq_false_iff_not_mem end Std.HashSet diff --git a/src/Std/Data/HashSet/RawDecidableEquiv.lean b/src/Std/Data/HashSet/RawDecidableEquiv.lean index ae56aa137aa8..fa8d1f9827c1 100644 --- a/src/Std/Data/HashSet/RawDecidableEquiv.lean +++ b/src/Std/Data/HashSet/RawDecidableEquiv.lean @@ -15,12 +15,12 @@ public section # Decidable equivalence for `HashSet.Raw` -/ - open Std.HashMap.Raw namespace Std.HashSet.Raw instance instDecidableEquiv {α : Type u} [DecidableEq α] [Hashable α] {m₁ m₂ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) := - let : Decidable (m₁.1 ~m m₂.1) := HashMap.Raw.instDecidableEquiv h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ + let : Decidable (m₁.1 ~m m₂.1) := HashMap.Raw.instDecidableEquiv h₁.out h₂.out; + decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.HashSet.Raw From b2c392f24594171bfbe0b41ab4927b6e2ad89cf3 Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Mon, 8 Dec 2025 08:14:05 +0000 Subject: [PATCH 70/72] chore: docstrings --- src/Std/Data/DHashMap/Basic.lean | 8 +++++--- src/Std/Data/DHashMap/Raw.lean | 8 +++++--- src/Std/Data/HashMap/Basic.lean | 3 +-- src/Std/Data/HashMap/Raw.lean | 3 +-- src/Std/Data/HashSet/Basic.lean | 5 ++++- src/Std/Data/HashSet/Raw.lean | 5 ++++- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Std/Data/DHashMap/Basic.lean b/src/Std/Data/DHashMap/Basic.lean index fc631a5f3f18..3d9f4befea07 100644 --- a/src/Std/Data/DHashMap/Basic.lean +++ b/src/Std/Data/DHashMap/Basic.lean @@ -360,14 +360,16 @@ instance [BEq α] [Hashable α] : Union (DHashMap α β) := ⟨union⟩ instance [BEq α] [Hashable α] : Inter (DHashMap α β) := ⟨inter⟩ instance [BEq α] [Hashable α] : SDiff (DHashMap α β) := ⟨diff⟩ -/-- Internal implementation detail of the hash map. -/ +/-- +Compares two hash maps using Boolean equality on keys and values. +Returns `true` if the maps contain the same key-value pairs, `false` otherwise. +-/ def beq [LawfulBEq α] [∀ k, BEq (β k)] (a b : DHashMap α β) : Bool := Raw₀.beq ⟨a.1, a.2.size_buckets_pos⟩ ⟨b.1, b.2.size_buckets_pos⟩ instance [LawfulBEq α] [∀ k, BEq (β k)] : BEq (DHashMap α β) := ⟨beq⟩ -/-- Internal implementation detail of the hash map. -/ -def Const.beq {β : Type v} [BEq α] [BEq β] (m₁ m₂ : DHashMap α (fun _ => β)) : Bool := +@[inherit_doc DHashMap.beq] def Const.beq {β : Type v} [BEq α] [BEq β] (m₁ m₂ : DHashMap α (fun _ => β)) : Bool := Raw₀.Const.beq ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ section Unverified diff --git a/src/Std/Data/DHashMap/Raw.lean b/src/Std/Data/DHashMap/Raw.lean index e9fac297b12e..5f8eead8f180 100644 --- a/src/Std/Data/DHashMap/Raw.lean +++ b/src/Std/Data/DHashMap/Raw.lean @@ -511,7 +511,10 @@ This function always merges the smaller map into the larger map, so the expected instance [BEq α] [Hashable α] : Inter (Raw α β) := ⟨inter⟩ -/-- Internal implementation detail of the hash map. -/ +/-- +Compares two hash maps using Boolean equality on keys and values. +Returns `true` if the maps contain the same key-value pairs, `false` otherwise. +-/ def beq [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] (m₁ m₂ : Raw α β) : Bool := if h₁ : 0 < m₁.buckets.size then if h₂ : 0 < m₂.buckets.size then @@ -523,8 +526,7 @@ def beq [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] (m₁ m₂ : R instance [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] : BEq (Raw α β) := ⟨beq⟩ -/-- Internal implementation detail of the hash map. -/ -def Const.beq {β : Type v} [BEq α] [Hashable α] [BEq β] (m₁ m₂ : Raw α (fun _ => β)) : Bool := +@[inherit_doc DHashMap.Raw.beq] def Const.beq {β : Type v} [BEq α] [Hashable α] [BEq β] (m₁ m₂ : Raw α (fun _ => β)) : Bool := if h₁ : 0 < m₁.buckets.size then if h₂ : 0 < m₂.buckets.size then Raw₀.Const.beq ⟨m₁, h₁⟩ ⟨m₂, h₂⟩ diff --git a/src/Std/Data/HashMap/Basic.lean b/src/Std/Data/HashMap/Basic.lean index 53b8e598377c..ab1d167bc395 100644 --- a/src/Std/Data/HashMap/Basic.lean +++ b/src/Std/Data/HashMap/Basic.lean @@ -278,8 +278,7 @@ instance [BEq α] [Hashable α] : Union (HashMap α β) := ⟨union⟩ instance [BEq α] [Hashable α] : Inter (HashMap α β) := ⟨inter⟩ -/-- Internal implementation detail of the hash map. -/ -def beq {β : Type v} [BEq α] [BEq β] (m₁ m₂ : HashMap α β) : Bool := +@[inherit_doc DHashMap.beq] def beq {β : Type v} [BEq α] [BEq β] (m₁ m₂ : HashMap α β) : Bool := DHashMap.Const.beq m₁.inner m₂.inner instance [BEq α] [BEq β] : BEq (HashMap α β) := ⟨beq⟩ diff --git a/src/Std/Data/HashMap/Raw.lean b/src/Std/Data/HashMap/Raw.lean index 50f98ca34a9e..48b60d460e81 100644 --- a/src/Std/Data/HashMap/Raw.lean +++ b/src/Std/Data/HashMap/Raw.lean @@ -250,8 +250,7 @@ instance [BEq α] [Hashable α] : Inter (Raw α β) := ⟨inter⟩ instance [BEq α] [Hashable α] : SDiff (Raw α β) := ⟨diff⟩ -/-- Internal implementation detail of the hash map. -/ -def beq {β : Type v} [BEq α] [Hashable α] [BEq β] (m₁ m₂ : Raw α β) : Bool := +@[inherit_doc DHashMap.Raw.beq] def beq {β : Type v} [BEq α] [Hashable α] [BEq β] (m₁ m₂ : Raw α β) : Bool := DHashMap.Raw.Const.beq m₁.inner m₂.inner instance [BEq α] [Hashable α] [BEq β] : BEq (Raw α β) := ⟨beq⟩ diff --git a/src/Std/Data/HashSet/Basic.lean b/src/Std/Data/HashSet/Basic.lean index f140b4a4376e..277fe06e42e3 100644 --- a/src/Std/Data/HashSet/Basic.lean +++ b/src/Std/Data/HashSet/Basic.lean @@ -260,7 +260,10 @@ This function always iterates through the smaller set, so the expected runtime i instance [BEq α] [Hashable α] : Inter (HashSet α) := ⟨inter⟩ -/-- Internal implementation detail of the hash map. -/ +/-- +Compares two hash sets using Boolean equality on keys. +Returns `true` if the sets contain the same keys pairs, `false` otherwise. +-/ def beq [BEq α] (m₁ m₂ : HashSet α) : Bool := HashMap.beq m₁.inner m₂.inner diff --git a/src/Std/Data/HashSet/Raw.lean b/src/Std/Data/HashSet/Raw.lean index e54fa921ec7f..9a43c18fe60b 100644 --- a/src/Std/Data/HashSet/Raw.lean +++ b/src/Std/Data/HashSet/Raw.lean @@ -244,7 +244,10 @@ This function always merges the smaller set into the larger set, so the expected instance [BEq α] [Hashable α] : Inter (Raw α) := ⟨inter⟩ -/-- Internal implementation detail of the hash map. -/ +/-- +Compares two hash sets using Boolean equality on keys. +Returns `true` if the sets contain the same keys pairs, `false` otherwise. +-/ def beq [BEq α] [Hashable α] (m₁ m₂ : Raw α) : Bool := HashMap.Raw.beq m₁.inner m₂.inner From d0e16d9f39266efc25491852777ce09ac44356ea Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Mon, 8 Dec 2025 11:50:57 +0000 Subject: [PATCH 71/72] chore: cleanup --- src/Std/Data/DHashMap/Basic.lean | 1 + src/Std/Data/DHashMap/Raw.lean | 15 +++++---------- src/Std/Data/DHashMap/RawLemmas.lean | 8 +++++--- src/Std/Data/ExtHashMap/Basic.lean | 3 +-- src/Std/Data/ExtHashSet/Basic.lean | 2 +- src/Std/Data/HashSet/Basic.lean | 3 ++- src/Std/Data/HashSet/Raw.lean | 3 ++- src/Std/Data/Internal/List/Associative.lean | 19 ++++++++----------- 8 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/Std/Data/DHashMap/Basic.lean b/src/Std/Data/DHashMap/Basic.lean index 3d9f4befea07..a96418fadabf 100644 --- a/src/Std/Data/DHashMap/Basic.lean +++ b/src/Std/Data/DHashMap/Basic.lean @@ -362,6 +362,7 @@ instance [BEq α] [Hashable α] : SDiff (DHashMap α β) := ⟨diff⟩ /-- Compares two hash maps using Boolean equality on keys and values. + Returns `true` if the maps contain the same key-value pairs, `false` otherwise. -/ def beq [LawfulBEq α] [∀ k, BEq (β k)] (a b : DHashMap α β) : Bool := diff --git a/src/Std/Data/DHashMap/Raw.lean b/src/Std/Data/DHashMap/Raw.lean index 5f8eead8f180..4982a2c7f87d 100644 --- a/src/Std/Data/DHashMap/Raw.lean +++ b/src/Std/Data/DHashMap/Raw.lean @@ -513,25 +513,20 @@ instance [BEq α] [Hashable α] : Inter (Raw α β) := ⟨inter⟩ /-- Compares two hash maps using Boolean equality on keys and values. + Returns `true` if the maps contain the same key-value pairs, `false` otherwise. -/ def beq [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] (m₁ m₂ : Raw α β) : Bool := - if h₁ : 0 < m₁.buckets.size then - if h₂ : 0 < m₂.buckets.size then - Raw₀.beq ⟨m₁, h₁⟩ ⟨m₂, h₂⟩ - else - false + if h : 0 < m₁.buckets.size ∧ 0 < m₂.buckets.size then + Raw₀.beq ⟨m₁, h.1⟩ ⟨m₂, h.2⟩ else false instance [BEq α] [Hashable α] [LawfulBEq α] [∀ k, BEq (β k)] : BEq (Raw α β) := ⟨beq⟩ @[inherit_doc DHashMap.Raw.beq] def Const.beq {β : Type v} [BEq α] [Hashable α] [BEq β] (m₁ m₂ : Raw α (fun _ => β)) : Bool := - if h₁ : 0 < m₁.buckets.size then - if h₂ : 0 < m₂.buckets.size then - Raw₀.Const.beq ⟨m₁, h₁⟩ ⟨m₂, h₂⟩ - else - false + if h : 0 < m₁.buckets.size ∧ 0 < m₂.buckets.size then + Raw₀.Const.beq ⟨m₁, h.1⟩ ⟨m₂, h.2⟩ else false diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index 2fa66c130486..ec09d57dfe9a 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -3766,11 +3766,13 @@ theorem Equiv.beq [∀ k, ReflBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : simp only [BEq.beq] simp_to_raw using Raw₀.Equiv.beq -theorem equiv_of_beq [∀ k, LawfulBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : beq m₁ m₂ = true) : m₁ ~m m₂ := by +theorem equiv_of_beq [∀ k, LawfulBEq (β k)] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : m₁ == m₂) : m₁ ~m m₂ := by revert h + simp only [BEq.beq] simp_to_raw using Raw₀.equiv_of_beq -theorem Equiv.beq_congr {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) (w₁ : m₁ ~m m₃) (w₂ : m₂ ~m m₄) : Raw.beq m₁ m₂ = Raw.beq m₃ m₄ := by +theorem Equiv.beq_congr {m₃ m₄ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) (h₃ : m₃.WF) (h₄ : m₄.WF) (w₁ : m₁ ~m m₃) (w₂ : m₂ ~m m₄) : (m₁ == m₂) = (m₃ == m₄) := by + simp only [BEq.beq] simp_to_raw using Raw₀.Equiv.beq_congr end BEq @@ -3782,7 +3784,7 @@ variable {β : Type v} {m₁ m₂ : Raw α (fun _ => β)} theorem Const.Equiv.beq [EquivBEq α] [LawfulHashable α] [BEq β] [ReflBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : m₁ ~m m₂) : beq m₁ m₂ := by simp_to_raw using Raw₀.Const.Equiv.beq -theorem Const.equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : beq m₁ m₂ = true ) : m₁ ~m m₂ := by +theorem Const.equiv_of_beq [LawfulBEq α] [BEq β] [LawfulBEq β] (h₁ : m₁.WF) (h₂ : m₂.WF) (h : beq m₁ m₂ = true) : m₁ ~m m₂ := by revert h simp_to_raw using Raw₀.Const.equiv_of_beq diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index 7c6765203a20..8245b1cc24a0 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -256,8 +256,7 @@ instance [EquivBEq α] [LawfulHashable α] [BEq β] [ReflBEq β] : ReflBEq (ExtH rfl := ExtDHashMap.Const.beq_of_eq _ _ rfl instance [LawfulBEq α] [BEq β] [LawfulBEq β] : LawfulBEq (ExtHashMap α β) where - eq_of_beq {a} {b} hyp := - by + eq_of_beq {a} {b} hyp := by have ⟨_⟩ := a have ⟨_⟩ := b simp only [mk.injEq] at |- hyp diff --git a/src/Std/Data/ExtHashSet/Basic.lean b/src/Std/Data/ExtHashSet/Basic.lean index cbf54e7f83b4..0dac4cf3212d 100644 --- a/src/Std/Data/ExtHashSet/Basic.lean +++ b/src/Std/Data/ExtHashSet/Basic.lean @@ -211,7 +211,7 @@ instance [EquivBEq α] [LawfulHashable α] : ReflBEq (ExtHashSet α) where rfl := ExtDHashMap.Const.beq_of_eq _ _ rfl instance [LawfulBEq α] : LawfulBEq (ExtHashSet α) where - eq_of_beq {a} {b} hyp := by + eq_of_beq {a} {b} hyp := by have ⟨⟨_⟩⟩ := a have ⟨⟨_⟩⟩ := b simp only [mk.injEq, ExtHashMap.mk.injEq] at |- hyp diff --git a/src/Std/Data/HashSet/Basic.lean b/src/Std/Data/HashSet/Basic.lean index 277fe06e42e3..5ee9a33425f6 100644 --- a/src/Std/Data/HashSet/Basic.lean +++ b/src/Std/Data/HashSet/Basic.lean @@ -262,7 +262,8 @@ instance [BEq α] [Hashable α] : Inter (HashSet α) := ⟨inter⟩ /-- Compares two hash sets using Boolean equality on keys. -Returns `true` if the sets contain the same keys pairs, `false` otherwise. + +Returns `true` if the sets contain the same keys, `false` otherwise. -/ def beq [BEq α] (m₁ m₂ : HashSet α) : Bool := HashMap.beq m₁.inner m₂.inner diff --git a/src/Std/Data/HashSet/Raw.lean b/src/Std/Data/HashSet/Raw.lean index 9a43c18fe60b..ac51893bdbfd 100644 --- a/src/Std/Data/HashSet/Raw.lean +++ b/src/Std/Data/HashSet/Raw.lean @@ -246,7 +246,8 @@ instance [BEq α] [Hashable α] : Inter (Raw α) := ⟨inter⟩ /-- Compares two hash sets using Boolean equality on keys. -Returns `true` if the sets contain the same keys pairs, `false` otherwise. + +Returns `true` if the sets contain the same keys, `false` otherwise. -/ def beq [BEq α] [Hashable α] (m₁ m₂ : Raw α) : Bool := HashMap.Raw.beq m₁.inner m₂.inner diff --git a/src/Std/Data/Internal/List/Associative.lean b/src/Std/Data/Internal/List/Associative.lean index 219efb10c9c4..a3cc3a8573ca 100644 --- a/src/Std/Data/Internal/List/Associative.lean +++ b/src/Std/Data/Internal/List/Associative.lean @@ -3589,12 +3589,9 @@ theorem length_le_length_of_containsKey [BEq α] [EquivBEq α] have hc := h hd.1 (by rw [containsKey_cons_self]) suffices tl.length ≤ (eraseKey hd.1 l₂).length by rw [List.length_eraseKey, hc] at this - simp at this - simp - have : l₂.length > 0 := by - cases l₂ - case nil => simp at hc - case cons => simp + simp only [↓reduceIte] at this + simp only [List.length_cons, ge_iff_le] + have : l₂.length > 0 := by cases l₂ <;> simp_all omega apply ih · rw [List.distinctKeys_cons_iff] at dl₁ @@ -3621,7 +3618,7 @@ theorem containsKey_of_length_eq [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : intro a ha apply Classical.byContradiction intro hb - simp at hb + simp only [Bool.not_eq_true] at hb suffices l₁.length < l₂.length by omega suffices l₁.length ≤ (eraseKey a l₂).length ∧ 1 + (eraseKey a l₂).length = l₂.length by omega apply And.intro @@ -3640,9 +3637,9 @@ theorem containsKey_of_length_eq [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : exact mem₂ · simp only [length_eraseKey, ha, ↓reduceIte] have : l₂.length > 0 := by - cases l₂ - · simp at ha - · simp + cases l₂ with + | nil => simp at ha + | _ => simp omega section @@ -7633,7 +7630,7 @@ theorem isEmpty_filter_key_iff [BEq α] [EquivBEq α] {f : α → Bool} simp only [getKey, getKey?_eq_getEntry?, this] at h exact h -theorem beqModel_eq_true_of_perm [BEq α] [LawfulBEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → beqModel l₁ l₂ := by +theorem beqModel_eq_true_of_perm [BEq α] [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] {l₁ l₂ : List ((a : α) × β a)} (hl₁ : DistinctKeys l₁) : l₁.Perm l₂ → beqModel l₁ l₂ := by intro hyp rw [beqModel, if_neg (by simpa using hyp.length_eq)] simp only [List.all_eq_true] From ffca990a04ae8c4859abfcc637e40285fd35bd3d Mon Sep 17 00:00:00 2001 From: Wojciech Rozowski Date: Fri, 12 Dec 2025 09:47:39 +0000 Subject: [PATCH 72/72] chore: make the statement more general --- src/Std/Data/DHashMap/DecidableEquiv.lean | 2 +- src/Std/Data/DHashMap/Internal/RawLemmas.lean | 2 +- src/Std/Data/DHashMap/RawDecidableEquiv.lean | 2 +- src/Std/Data/ExtDHashMap/Basic.lean | 2 +- src/Std/Data/ExtHashMap/Basic.lean | 2 +- src/Std/Data/ExtHashSet/Basic.lean | 2 +- src/Std/Data/HashMap/DecidableEquiv.lean | 2 +- src/Std/Data/HashMap/RawDecidableEquiv.lean | 2 +- src/Std/Data/HashSet/DecidableEquiv.lean | 2 +- src/Std/Data/HashSet/RawDecidableEquiv.lean | 2 +- tests/lean/run/exthashset_deceq.lean | 24 +++++++++++++++++++ 11 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 tests/lean/run/exthashset_deceq.lean diff --git a/src/Std/Data/DHashMap/DecidableEquiv.lean b/src/Std/Data/DHashMap/DecidableEquiv.lean index 64e0419828f8..ed4df15730d4 100644 --- a/src/Std/Data/DHashMap/DecidableEquiv.lean +++ b/src/Std/Data/DHashMap/DecidableEquiv.lean @@ -18,7 +18,7 @@ open Std.DHashMap.Internal namespace Std.DHashMap -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := +instance {α : Type u} {β : α → Type v} [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] (m₁ m₂ : DHashMap α β) : Decidable (m₁ ~m m₂) := let : Decidable (m₁.1.Equiv m₂.1) := Raw₀.decidableEquiv ⟨m₁.1, m₁.2.size_buckets_pos⟩ ⟨m₂.1, m₂.2.size_buckets_pos⟩ m₁.2 m₂.2; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 7861df616d9c..2a9dfb1bca8b 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -5161,7 +5161,7 @@ end Raw₀ namespace Raw₀ /-- Internal implementation detail -/ -def decidableEquiv [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] (m₁ m₂ : Raw₀ α β) (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : Decidable (m₁.1.Equiv m₂.1) := +def decidableEquiv [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] (m₁ m₂ : Raw₀ α β) (h₁ : m₁.val.WF) (h₂ : m₂.val.WF) : Decidable (m₁.1.Equiv m₂.1) := decidable_of_iff _ ⟨Raw₀.equiv_of_beq h₁ h₂, Raw₀.Equiv.beq h₁ h₂⟩ end Raw₀ diff --git a/src/Std/Data/DHashMap/RawDecidableEquiv.lean b/src/Std/Data/DHashMap/RawDecidableEquiv.lean index 5c8c803ac8bb..3542f566d427 100644 --- a/src/Std/Data/DHashMap/RawDecidableEquiv.lean +++ b/src/Std/Data/DHashMap/RawDecidableEquiv.lean @@ -18,7 +18,7 @@ open Std.DHashMap.Internal namespace Std.DHashMap.Raw -instance instDecidableEquiv {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) := +instance instDecidableEquiv {α : Type u} {β : α → Type v} [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) := Raw₀.decidableEquiv ⟨m₁, h₁.size_buckets_pos⟩ ⟨m₂, h₂.size_buckets_pos⟩ h₁ h₂ end Std.DHashMap.Raw diff --git a/src/Std/Data/ExtDHashMap/Basic.lean b/src/Std/Data/ExtDHashMap/Basic.lean index 7984cd8f4ed4..67be6c8517a0 100644 --- a/src/Std/Data/ExtDHashMap/Basic.lean +++ b/src/Std/Data/ExtDHashMap/Basic.lean @@ -371,7 +371,7 @@ instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, ReflBEq (β k)] : ReflBEq (E instance [LawfulBEq α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : LawfulBEq (ExtDHashMap α β) where eq_of_beq {m₁} {m₂} := m₁.inductionOn₂ m₂ fun _ _ hyp => sound <| DHashMap.equiv_of_beq hyp -instance {α : Type u} {β : α → Type v} [DecidableEq α] [Hashable α] [∀ k, DecidableEq (β k)] : DecidableEq (ExtDHashMap α β) := +instance {α : Type u} {β : α → Type v} [BEq α] [LawfulBEq α] [Hashable α] [∀ k, BEq (β k)] [∀ k, LawfulBEq (β k)] : DecidableEq (ExtDHashMap α β) := fun _ _ => decidable_of_iff _ beq_iff_eq namespace Const diff --git a/src/Std/Data/ExtHashMap/Basic.lean b/src/Std/Data/ExtHashMap/Basic.lean index 226588808ab1..9316f13e58f1 100644 --- a/src/Std/Data/ExtHashMap/Basic.lean +++ b/src/Std/Data/ExtHashMap/Basic.lean @@ -262,7 +262,7 @@ instance [LawfulBEq α] [BEq β] [LawfulBEq β] : LawfulBEq (ExtHashMap α β) w simp only [mk.injEq] at |- hyp exact ExtDHashMap.Const.eq_of_beq _ _ hyp -instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] : DecidableEq (ExtHashMap α β) := +instance {α : Type u} {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] [BEq β] [LawfulBEq β] : DecidableEq (ExtHashMap α β) := fun _ _ => decidable_of_iff _ beq_iff_eq @[inline, inherit_doc ExtDHashMap.inter] diff --git a/src/Std/Data/ExtHashSet/Basic.lean b/src/Std/Data/ExtHashSet/Basic.lean index 1f2d2f04f456..dd83b64078cf 100644 --- a/src/Std/Data/ExtHashSet/Basic.lean +++ b/src/Std/Data/ExtHashSet/Basic.lean @@ -217,7 +217,7 @@ instance [LawfulBEq α] : LawfulBEq (ExtHashSet α) where simp only [mk.injEq, ExtHashMap.mk.injEq] at |- hyp exact ExtDHashMap.Const.eq_of_beq _ _ hyp -instance {α : Type u} [DecidableEq α] [Hashable α] : DecidableEq (ExtHashSet α) := +instance {α : Type u} [BEq α] [LawfulBEq α] [Hashable α] : DecidableEq (ExtHashSet α) := fun _ _ => decidable_of_iff _ beq_iff_eq /-- diff --git a/src/Std/Data/HashMap/DecidableEquiv.lean b/src/Std/Data/HashMap/DecidableEquiv.lean index a3149244d3c7..370ce2bc4ea7 100644 --- a/src/Std/Data/HashMap/DecidableEquiv.lean +++ b/src/Std/Data/HashMap/DecidableEquiv.lean @@ -17,7 +17,7 @@ public section namespace Std.HashMap -instance {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] (m₁ m₂ : HashMap α β) : Decidable (m₁ ~m m₂) := +instance {α : Type u} {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] [BEq β] [LawfulBEq β] (m₁ m₂ : HashMap α β) : Decidable (m₁ ~m m₂) := decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.HashMap diff --git a/src/Std/Data/HashMap/RawDecidableEquiv.lean b/src/Std/Data/HashMap/RawDecidableEquiv.lean index cf8a667e87d3..530f9f0caebe 100644 --- a/src/Std/Data/HashMap/RawDecidableEquiv.lean +++ b/src/Std/Data/HashMap/RawDecidableEquiv.lean @@ -19,7 +19,7 @@ open Std.DHashMap.Raw namespace Std.HashMap.Raw -instance instDecidableEquiv {α : Type u} {β : Type v} [DecidableEq α] [Hashable α] [DecidableEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) := +instance instDecidableEquiv {α : Type u} {β : Type v} [BEq α] [LawfulBEq α] [Hashable α] [BEq β] [LawfulBEq β] {m₁ m₂ : Raw α β} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) := let : Decidable (m₁.1 ~m m₂.1) := DHashMap.Raw.instDecidableEquiv h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ diff --git a/src/Std/Data/HashSet/DecidableEquiv.lean b/src/Std/Data/HashSet/DecidableEquiv.lean index 8baa49a051f2..7fba686c8a20 100644 --- a/src/Std/Data/HashSet/DecidableEquiv.lean +++ b/src/Std/Data/HashSet/DecidableEquiv.lean @@ -17,7 +17,7 @@ public section namespace Std.HashSet -instance {α : Type u} [DecidableEq α] [Hashable α] (m₁ m₂ : HashSet α) : Decidable (m₁ ~m m₂) := +instance {α : Type u} [BEq α] [LawfulBEq α] [Hashable α] (m₁ m₂ : HashSet α) : Decidable (m₁ ~m m₂) := decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ end Std.HashSet diff --git a/src/Std/Data/HashSet/RawDecidableEquiv.lean b/src/Std/Data/HashSet/RawDecidableEquiv.lean index fa8d1f9827c1..b008aa8ec56c 100644 --- a/src/Std/Data/HashSet/RawDecidableEquiv.lean +++ b/src/Std/Data/HashSet/RawDecidableEquiv.lean @@ -19,7 +19,7 @@ open Std.HashMap.Raw namespace Std.HashSet.Raw -instance instDecidableEquiv {α : Type u} [DecidableEq α] [Hashable α] {m₁ m₂ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) := +instance instDecidableEquiv {α : Type u} [BEq α] [LawfulBEq α] [Hashable α] {m₁ m₂ : Raw α} (h₁ : m₁.WF) (h₂ : m₂.WF) : Decidable (m₁ ~m m₂) := let : Decidable (m₁.1 ~m m₂.1) := HashMap.Raw.instDecidableEquiv h₁.out h₂.out; decidable_of_iff _ ⟨fun h => ⟨h⟩, fun h => h.1⟩ diff --git a/tests/lean/run/exthashset_deceq.lean b/tests/lean/run/exthashset_deceq.lean new file mode 100644 index 000000000000..06dc6753a17d --- /dev/null +++ b/tests/lean/run/exthashset_deceq.lean @@ -0,0 +1,24 @@ +import Std.Data.ExtHashSet +open Std + +@[ext] +structure A where + a : Nat + b : Nat +deriving Hashable + +instance : BEq A where + beq x y := x.b == y.b && x.a == y.a + +@[simp] +theorem A.beq_eq {x y : A} : (x == y) = (x.b == y.b && x.a == y.a) := rfl + +instance : LawfulBEq A where + rfl {x} := by simp + eq_of_beq {x y} := by grind [A.beq_eq, A.ext] + +instance : DecidableEq A := + fun x y => by simp [A.ext_iff]; infer_instance + +example : Decidable (ExtHashSet.ofList [A.mk 1 2] = ExtHashSet.ofList [A.mk 1 2]) := by + infer_instance