diff --git a/src/Std/Data/DHashMap/Basic.lean b/src/Std/Data/DHashMap/Basic.lean index 2c78504a9007..d1a73ede28f1 100644 --- a/src/Std/Data/DHashMap/Basic.lean +++ b/src/Std/Data/DHashMap/Basic.lean @@ -290,24 +290,12 @@ This function ensures that the value is used linearly. ⟨(Raw₀.Const.insertManyIfNewUnit ⟨m.1, m.2.size_buckets_pos⟩ l).1, (Raw₀.Const.insertManyIfNewUnit ⟨m.1, m.2.size_buckets_pos⟩ l).2 _ Raw.WF.insertIfNew₀ m.2⟩ -@[inline, inherit_doc Raw.ofList] def ofList [BEq α] [Hashable α] (l : List ((a : α) × β a)) : - DHashMap α β := - insertMany ∅ l - /-- Computes the union of the given hash maps, by traversing `m₂` and inserting its elements into `m₁`. -/ @[inline] def union [BEq α] [Hashable α] (m₁ m₂ : DHashMap α β) : DHashMap α β := m₂.fold (init := m₁) fun acc x => acc.insert x instance [BEq α] [Hashable α] : Union (DHashMap α β) := ⟨union⟩ -@[inline, inherit_doc Raw.Const.ofList] def Const.ofList {β : Type v} [BEq α] [Hashable α] - (l : List (α × β)) : DHashMap α (fun _ => β) := - Const.insertMany ∅ l - -@[inline, inherit_doc Raw.Const.unitOfList] def Const.unitOfList [BEq α] [Hashable α] (l : List α) : - DHashMap α (fun _ => Unit) := - Const.insertManyIfNewUnit ∅ l - @[inline, inherit_doc Raw.Const.unitOfArray] def Const.unitOfArray [BEq α] [Hashable α] (l : Array α) : DHashMap α (fun _ => Unit) := Const.insertManyIfNewUnit ∅ l @@ -321,4 +309,16 @@ instance [BEq α] [Hashable α] [Repr α] [(a : α) → Repr (β a)] : Repr (DHa end Unverified +@[inline, inherit_doc Raw.ofList] def ofList [BEq α] [Hashable α] (l : List ((a : α) × β a)) : + DHashMap α β := + insertMany ∅ l + +@[inline, inherit_doc Raw.Const.ofList] def Const.ofList {β : Type v} [BEq α] [Hashable α] + (l : List (α × β)) : DHashMap α (fun _ => β) := + Const.insertMany ∅ l + +@[inline, inherit_doc Raw.Const.unitOfList] def Const.unitOfList [BEq α] [Hashable α] (l : List α) : + DHashMap α (fun _ => Unit) := + Const.insertManyIfNewUnit ∅ l + end Std.DHashMap diff --git a/src/Std/Data/DHashMap/Internal/List/Associative.lean b/src/Std/Data/DHashMap/Internal/List/Associative.lean index d262cd88e291..e56d6864e7a9 100644 --- a/src/Std/Data/DHashMap/Internal/List/Associative.lean +++ b/src/Std/Data/DHashMap/Internal/List/Associative.lean @@ -7,6 +7,7 @@ prelude import Init.Data.BEq import Init.Data.Nat.Simproc import Init.Data.List.Perm +import Init.Data.List.Find import Std.Data.DHashMap.Internal.List.Defs /-! @@ -257,6 +258,15 @@ theorem containsKey_eq_isSome_getEntry? [BEq α] {l : List ((a : α) × β a)} { · simp [getEntry?_cons_of_false h, h, ih] · simp [getEntry?_cons_of_true h, h] +theorem containsKey_eq_contains_map_fst [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} + {k : α} : containsKey k l = (l.map Sigma.fst).contains k := by + induction l with + | nil => simp + | cons hd tl ih => + rw [containsKey_cons, ih] + simp only [List.map_cons, List.contains_cons] + rw [BEq.comm] + theorem isEmpty_eq_false_of_containsKey [BEq α] {l : List ((a : α) × β a)} {a : α} (h : containsKey a l = true) : l.isEmpty = false := by cases l <;> simp_all @@ -663,7 +673,7 @@ theorem isEmpty_replaceEntry [BEq α] {l : List ((a : α) × β a)} {k : α} {v (replaceEntry k v l).isEmpty = l.isEmpty := by induction l using assoc_induction · simp - · simp [replaceEntry_cons, cond_eq_if] + · simp only [replaceEntry_cons, cond_eq_if, List.isEmpty_cons] split <;> simp theorem getEntry?_replaceEntry_of_containsKey_eq_false [BEq α] {l : List ((a : α) × β a)} {a k : α} @@ -681,7 +691,7 @@ theorem getEntry?_replaceEntry_of_false [BEq α] [PartialEquivBEq α] {l : List · rw [replaceEntry_cons_of_false h', getEntry?_cons, getEntry?_cons, ih] · rw [replaceEntry_cons_of_true h'] have hk : (k' == a) = false := BEq.neq_of_beq_of_neq h' h - simp [getEntry?_cons_of_false h, getEntry?_cons_of_false hk] + simp only [getEntry?_cons_of_false h, getEntry?_cons_of_false hk] theorem getEntry?_replaceEntry_of_true [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {a k : α} {v : β k} (hl : containsKey k l = true) (h : k == a) : @@ -874,6 +884,11 @@ theorem containsKey_of_mem [BEq α] [ReflBEq α] {l : List ((a : α) × β a)} { theorem DistinctKeys.nil [BEq α] : DistinctKeys ([] : List ((a : α) × β a)) := ⟨by simp⟩ +theorem DistinctKeys.def [BEq α] {l : List ((a : α) × β a)} : + DistinctKeys l ↔ l.Pairwise (fun a b => (a.1 == b.1) = false) := + ⟨fun h => by simpa [keys_eq_map, List.pairwise_map] using h.distinct, + fun h => ⟨by simpa [keys_eq_map, List.pairwise_map] using h⟩⟩ + open List theorem DistinctKeys.perm_keys [BEq α] [PartialEquivBEq α] {l l' : List ((a : α) × β a)} @@ -909,6 +924,10 @@ theorem containsKey_eq_false_iff_forall_mem_keys [BEq α] [PartialEquivBEq α] (containsKey a l) = false ↔ ∀ a' ∈ keys l, (a == a') = false := by simp only [Bool.eq_false_iff, ne_eq, containsKey_iff_exists, not_exists, not_and] +theorem containsKey_eq_false_iff [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {a : α} : + containsKey a l = false ↔ ∀ (b : ((a : α) × β a)), b ∈ l → (a == b.fst) = false := by + simp [containsKey_eq_false_iff_forall_mem_keys, keys_eq_map] + @[simp] theorem distinctKeys_cons_iff [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} : DistinctKeys (⟨k, v⟩ :: l) ↔ DistinctKeys l ∧ (containsKey k l) = false := by @@ -963,6 +982,18 @@ theorem DistinctKeys.replaceEntry [BEq α] [PartialEquivBEq α] {l : List ((a : refine ⟨h.1, ?_⟩ simpa [containsKey_congr (BEq.symm hk'k)] using h.2 +theorem getEntry?_of_mem [BEq α] [PartialEquivBEq α] + {l : List ((a : α) × β a)} (hl : DistinctKeys l) + {k k' : α} (hk : k == k') {v : β k} (hkv : ⟨k, v⟩ ∈ l) : + getEntry? k' l = some ⟨k, v⟩ := by + induction l using assoc_induction with + | nil => simp at hkv + | cons k₁ v₁ t ih => + obtain ⟨⟨⟩⟩|hkv := List.mem_cons.1 hkv + · rw [getEntry?_cons_of_true hk] + · rw [getEntry?_cons_of_false, ih hl.tail hkv] + exact BEq.neq_of_neq_of_beq (containsKey_eq_false_iff.1 hl.containsKey_eq_false _ hkv) hk + /-- Internal implementation detail of the hash map -/ def insertEntry [BEq α] (k : α) (v : β k) (l : List ((a : α) × β a)) : List ((a : α) × β a) := bif containsKey k l then replaceEntry k v l else ⟨k, v⟩ :: l @@ -1214,6 +1245,16 @@ theorem insertEntryIfNew_of_containsKey_eq_false [BEq α] {l : List ((a : α) × {v : β k} (h : containsKey k l = false) : insertEntryIfNew k v l = ⟨k, v⟩ :: l := by simp_all [insertEntryIfNew] +theorem DistinctKeys.insertEntryIfNew [BEq α] [PartialEquivBEq α] {k : α} {v : β k} + {l : List ((a : α) × β a)} (h: DistinctKeys l): + DistinctKeys (insertEntryIfNew k v l) := by + simp only [Std.DHashMap.Internal.List.insertEntryIfNew, cond_eq_if] + split + · exact h + · rw [distinctKeys_cons_iff] + rename_i h' + simp [h, h'] + @[simp] theorem isEmpty_insertEntryIfNew [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} : (insertEntryIfNew k v l).isEmpty = false := by @@ -1845,6 +1886,836 @@ theorem eraseKey_append_of_containsKey_right_eq_false [BEq α] {l l' : List ((a · rw [cond_false, cond_false, ih, List.cons_append] · rw [cond_true, cond_true] +/-- Internal implementation detail of the hash map -/ +def insertList [BEq α] (l toInsert : List ((a : α) × β a)) : List ((a : α) × β a) := + match toInsert with + | .nil => l + | .cons ⟨k, v⟩ toInsert => insertList (insertEntry k v l) toInsert + +theorem DistinctKeys.insertList [BEq α] [PartialEquivBEq α] {l₁ l₂ : List ((a : α) × β a)} + (h : DistinctKeys l₁) : + DistinctKeys (insertList l₁ l₂) := by + induction l₂ using assoc_induction generalizing l₁ + · simpa [insertList] + · rename_i k v t ih + rw [insertList.eq_def] + exact ih h.insertEntry + +theorem insertList_perm_of_perm_first [BEq α] [EquivBEq α] {l1 l2 toInsert : List ((a : α) × β a)} + (h : Perm l1 l2) (distinct : DistinctKeys l1) : + Perm (insertList l1 toInsert) (insertList l2 toInsert) := by + induction toInsert generalizing l1 l2 with + | nil => simp [insertList, h] + | cons hd tl ih => + simp only [insertList] + apply ih (insertEntry_of_perm distinct h) (DistinctKeys.insertEntry distinct) + +theorem insertList_cons_perm [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : α) × β a)} + {p : (a : α) × β a} (hl₁ : DistinctKeys l₁) (hl₂ : DistinctKeys (p :: l₂)) : + (insertList l₁ (p :: l₂)).Perm (insertEntry p.1 p.2 (insertList l₁ l₂)) := by + induction l₂ generalizing p l₁ + · simp [insertList] + · rename_i h t ih + rw [insertList] + refine (ih hl₁.insertEntry hl₂.tail).trans + ((insertEntry_of_perm hl₁.insertList + (ih hl₁ (distinctKeys_of_sublist (by simp) hl₂))).trans + (List.Perm.trans ?_ (insertEntry_of_perm hl₁.insertList.insertEntry + (ih hl₁ (distinctKeys_of_sublist (by simp) hl₂)).symm))) + apply getEntry?_ext hl₁.insertList.insertEntry.insertEntry + hl₁.insertList.insertEntry.insertEntry (fun k => ?_) + simp only [getEntry?_insertEntry] + split <;> rename_i hp <;> split <;> rename_i hh <;> try rfl + rw [DistinctKeys.def] at hl₂ + have := List.rel_of_pairwise_cons hl₂ (List.mem_cons_self _ _) + simp [BEq.trans hh (BEq.symm hp)] at this + +theorem getEntry?_insertList [BEq α] [EquivBEq α] + {l toInsert : List ((a : α) × β a)} + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) (k : α) : + getEntry? k (insertList l toInsert) = (getEntry? k toInsert).or (getEntry? k l) := by + induction toInsert generalizing l with + | nil => simp [insertList] + | cons h t ih => + rw [getEntry?_of_perm distinct_l.insertList + (insertList_cons_perm distinct_l (DistinctKeys.def.2 distinct_toInsert)), + getEntry?_insertEntry] + cases hk : h.1 == k + · simp only [Bool.false_eq_true, ↓reduceIte] + rw [ih distinct_l distinct_toInsert.tail, getEntry?_cons_of_false hk] + · simp only [↓reduceIte] + rw [getEntry?_cons_of_true hk, Option.some_or] + +theorem getEntry?_insertList_of_contains_eq_false [BEq α] [PartialEquivBEq α] + {l toInsert : List ((a : α) × β a)} {k : α} + (not_contains : containsKey k toInsert = false) : + getEntry? k (insertList l toInsert) = getEntry? k l := by + induction toInsert generalizing l with + | nil => simp [insertList] + | cons h t ih => + unfold insertList + rw [containsKey_cons_eq_false] at not_contains + rw [ih not_contains.right, getEntry?_insertEntry] + simp [not_contains] + +theorem getEntry?_insertList_of_contains_eq_true [BEq α] [EquivBEq α] + {l toInsert : List ((a : α) × β a)} {k : α} + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (contains : containsKey k toInsert = true) : + getEntry? k (insertList l toInsert) = getEntry? k toInsert := by + rw [getEntry?_insertList distinct_l distinct_toInsert] + rw [containsKey_eq_isSome_getEntry?] at contains + exact Option.or_of_isSome contains + +theorem containsKey_insertList [BEq α] [PartialEquivBEq α] {l toInsert : List ((a : α) × β a)} + {k : α} : containsKey k (List.insertList l toInsert) = + (containsKey k l || (toInsert.map Sigma.fst).contains k) := by + induction toInsert generalizing l with + | nil => simp only [insertList, List.map_nil, List.elem_nil, Bool.or_false] + | cons hd tl ih => + unfold insertList + rw [ih] + rw [containsKey_insertEntry] + simp only [Bool.or_eq_true, List.map_cons, List.contains_cons] + rw [BEq.comm] + conv => left; left; rw [Bool.or_comm] + rw [Bool.or_assoc] + +theorem containsKey_of_containsKey_insertList [BEq α] [PartialEquivBEq α] + {l toInsert : List ((a : α) × β a)} {k : α} (h₁ : containsKey k (insertList l toInsert)) + (h₂ : (toInsert.map Sigma.fst).contains k = false) : containsKey k l := by + rw [containsKey_insertList, h₂] at h₁; simp at h₁; exact h₁ + +theorem getValueCast?_insertList_of_contains_eq_false [BEq α] [LawfulBEq α] + {l toInsert : List ((a : α) × β a)} {k : α} + (not_contains : (toInsert.map Sigma.fst).contains k = false) : + getValueCast? k (insertList l toInsert) = getValueCast? k l := by + rw [← containsKey_eq_contains_map_fst] at not_contains + rw [getValueCast?_eq_getEntry?, getValueCast?_eq_getEntry?] + apply Option.dmap_congr + rw [getEntry?_insertList_of_contains_eq_false not_contains] + +theorem getValueCast?_insertList_of_mem [BEq α] [LawfulBEq α] + {l toInsert : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') {v : β k} + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ toInsert) : + getValueCast? k' (insertList l toInsert) = + some (cast (by congr; exact LawfulBEq.eq_of_beq k_beq) v) := by + rw [getValueCast?_eq_getEntry?] + have : getEntry? k' (insertList l toInsert) = getEntry? k' toInsert := by + apply getEntry?_insertList_of_contains_eq_true distinct_l distinct_toInsert + apply containsKey_of_beq _ k_beq + exact containsKey_of_mem mem + rw [← DistinctKeys.def] at distinct_toInsert + rw [getEntry?_of_mem distinct_toInsert k_beq mem] at this + rw [Option.dmap_congr this] + simp + +theorem getValueCast_insertList_of_contains_eq_false [BEq α] [LawfulBEq α] + {l toInsert : List ((a : α) × β a)} {k : α} + (not_contains : (toInsert.map Sigma.fst).contains k = false) + {h} : + getValueCast k (insertList l toInsert) h = + getValueCast k l (containsKey_of_containsKey_insertList h not_contains) := by + rw [← Option.some_inj, ← getValueCast?_eq_some_getValueCast, ← getValueCast?_eq_some_getValueCast, + getValueCast?_insertList_of_contains_eq_false] + exact not_contains + +theorem getValueCast_insertList_of_mem [BEq α] [LawfulBEq α] + {l toInsert : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') (v : β k) + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ toInsert) + {h} : + getValueCast k' (insertList l toInsert) h = + cast (by congr; exact LawfulBEq.eq_of_beq k_beq) v := by + rw [← Option.some_inj, ← getValueCast?_eq_some_getValueCast, + getValueCast?_insertList_of_mem k_beq distinct_l distinct_toInsert mem] + +theorem getValueCast!_insertList_of_contains_eq_false [BEq α] [LawfulBEq α] + {l toInsert : List ((a : α) × β a)} {k : α} [Inhabited (β k)] + (not_contains : (toInsert.map Sigma.fst).contains k = false) : + getValueCast! k (insertList l toInsert) = getValueCast! k l := by + rw [getValueCast!_eq_getValueCast?, getValueCast!_eq_getValueCast?, + getValueCast?_insertList_of_contains_eq_false not_contains] + +theorem getValueCast!_insertList_of_mem [BEq α] [LawfulBEq α] + {l toInsert : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') (v : β k) [Inhabited (β k')] + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ toInsert) : + getValueCast! k' (insertList l toInsert) = + cast (by congr; exact LawfulBEq.eq_of_beq k_beq) v := by + rw [getValueCast!_eq_getValueCast?, + getValueCast?_insertList_of_mem k_beq distinct_l distinct_toInsert mem, Option.get!_some] + +theorem getValueCastD_insertList_of_contains_eq_false [BEq α] [LawfulBEq α] + {l toInsert : List ((a : α) × β a)} {k : α} {fallback : β k} + (not_mem : (toInsert.map Sigma.fst).contains k = false) : + getValueCastD k (insertList l toInsert) fallback = getValueCastD k l fallback := by + rw [getValueCastD_eq_getValueCast?, getValueCastD_eq_getValueCast?, + getValueCast?_insertList_of_contains_eq_false not_mem] + +theorem getValueCastD_insertList_of_mem [BEq α] [LawfulBEq α] + {l toInsert : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') {v : β k} {fallback : β k'} + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ toInsert) : + getValueCastD k' (insertList l toInsert) fallback = + cast (by congr; exact LawfulBEq.eq_of_beq k_beq) v := by + rw [getValueCastD_eq_getValueCast?, + getValueCast?_insertList_of_mem k_beq distinct_l distinct_toInsert mem, Option.getD_some] + +theorem getKey?_insertList_of_contains_eq_false [BEq α] [EquivBEq α] + {l toInsert : List ((a : α) × β a)} {k : α} + (not_contains : (toInsert.map Sigma.fst).contains k = false) : + getKey? k (insertList l toInsert) = getKey? k l := by + rw [← containsKey_eq_contains_map_fst] at not_contains + rw [getKey?_eq_getEntry?, getKey?_eq_getEntry?, + getEntry?_insertList_of_contains_eq_false not_contains] + +theorem getKey?_insertList_of_mem [BEq α] [EquivBEq α] + {l toInsert : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ toInsert.map Sigma.fst) : + getKey? k' (insertList l toInsert) = some k := by + rcases List.mem_map.1 mem with ⟨⟨k, v⟩, pair_mem, rfl⟩ + rw [getKey?_eq_getEntry?, getEntry?_insertList distinct_l distinct_toInsert, + getEntry?_of_mem (DistinctKeys.def.2 distinct_toInsert) k_beq pair_mem, Option.some_or, + Option.map_some'] + +theorem getKey_insertList_of_contains_eq_false [BEq α] [EquivBEq α] + {l toInsert : List ((a : α) × β a)} {k : α} + (not_contains : (toInsert.map Sigma.fst).contains k = false) + {h} : + getKey k (insertList l toInsert) h = + getKey k l (containsKey_of_containsKey_insertList h not_contains) := by + rw [← Option.some_inj, ← getKey?_eq_some_getKey, + getKey?_insertList_of_contains_eq_false not_contains, getKey?_eq_some_getKey] + +theorem getKey_insertList_of_mem [BEq α] [EquivBEq α] + {l toInsert : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ toInsert.map Sigma.fst) + {h} : + getKey k' (insertList l toInsert) h = k := by + rw [← Option.some_inj, ← getKey?_eq_some_getKey, + getKey?_insertList_of_mem k_beq distinct_l distinct_toInsert mem] + +theorem getKey!_insertList_of_contains_eq_false [BEq α] [EquivBEq α] [Inhabited α] + {l toInsert : List ((a : α) × β a)} {k : α} + (contains_false : (toInsert.map Sigma.fst).contains k = false) : + getKey! k (insertList l toInsert) = getKey! k l := by + rw [getKey!_eq_getKey?, getKey?_insertList_of_contains_eq_false contains_false, getKey!_eq_getKey?] + +theorem getKey!_insertList_of_mem [BEq α] [EquivBEq α] [Inhabited α] + {l toInsert : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ toInsert.map Sigma.fst) : + getKey! k' (insertList l toInsert) = k := by + rw [getKey!_eq_getKey?, getKey?_insertList_of_mem k_beq distinct_l distinct_toInsert mem, + Option.get!_some] + +theorem getKeyD_insertList_of_contains_eq_false [BEq α] [EquivBEq α] + {l toInsert : List ((a : α) × β a)} {k fallback : α} + (not_contains : (toInsert.map Sigma.fst).contains k = false) : + getKeyD k (insertList l toInsert) fallback = getKeyD k l fallback := by + rw [getKeyD_eq_getKey?, getKey?_insertList_of_contains_eq_false not_contains, getKeyD_eq_getKey?] + +theorem getKeyD_insertList_of_mem [BEq α] [EquivBEq α] + {l toInsert : List ((a : α) × β a)} + {k k' fallback : α} (k_beq : k == k') + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ toInsert.map Sigma.fst) : + getKeyD k' (insertList l toInsert) fallback = k := by + rw [getKeyD_eq_getKey?, getKey?_insertList_of_mem k_beq distinct_l distinct_toInsert mem, + Option.getD_some] + +theorem perm_insertList [BEq α] [EquivBEq α] + {l toInsert : List ((a : α) × β a)} + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (distinct_both : ∀ (a : α), containsKey a l → (toInsert.map Sigma.fst).contains a = false) : + Perm (insertList l toInsert) (l ++ toInsert) := by + rw [← DistinctKeys.def] at distinct_toInsert + induction toInsert generalizing l with + | nil => simp only [insertList, List.append_nil, Perm.refl] + | cons hd tl ih => + simp only [List.map_cons, List.contains_cons, Bool.or_eq_false_iff] at distinct_both + refine (insertList_cons_perm distinct_l distinct_toInsert).trans ?_ + rw [insertEntry_of_containsKey_eq_false] + · refine (Perm.cons _ (ih distinct_l (distinct_toInsert).tail ?_)).trans List.perm_middle.symm + exact fun a ha => (distinct_both a ha).2 + · simp only [containsKey_insertList, Bool.or_eq_false_iff, ← containsKey_eq_contains_map_fst] + refine ⟨Bool.not_eq_true _ ▸ fun h => ?_, distinct_toInsert.containsKey_eq_false⟩ + simpa using (distinct_both _ h).1 + +theorem length_insertList [BEq α] [EquivBEq α] + {l toInsert : List ((a : α) × β a)} + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (distinct_both : ∀ (a : α), containsKey a l → (toInsert.map Sigma.fst).contains a = false) : + (insertList l toInsert).length = l.length + toInsert.length := by + simpa using (perm_insertList distinct_l distinct_toInsert distinct_both).length_eq + +theorem length_le_length_insertList [BEq α] + {l toInsert : List ((a : α) × β a)} : + l.length ≤ (insertList l toInsert).length := by + induction toInsert generalizing l with + | nil => apply Nat.le_refl + | cons hd tl ih => exact Nat.le_trans length_le_length_insertEntry ih + +theorem length_insertList_le [BEq α] + {l toInsert : List ((a : α) × β a)} : + (insertList l toInsert).length ≤ l.length + toInsert.length := by + induction toInsert generalizing l with + | nil => simp only [insertList, List.length_nil, Nat.add_zero, Nat.le_refl] + | cons hd tl ih => + simp only [insertList, List.length_cons] + apply Nat.le_trans ih + rw [Nat.add_comm tl.length 1, ← Nat.add_assoc] + apply Nat.add_le_add length_insertEntry_le (Nat.le_refl _) + +theorem isEmpty_insertList [BEq α] + {l toInsert : List ((a : α) × β a)} : + (List.insertList l toInsert).isEmpty = (l.isEmpty && toInsert.isEmpty) := by + induction toInsert generalizing l with + | nil => simp [insertList] + | cons hd tl ih => + rw [insertList, List.isEmpty_cons, ih, isEmpty_insertEntry] + simp + +section + +variable {β : Type v} + +/-- Internal implementation detail of the hash map -/ +def Prod.toSigma (p : α × β) : ((_ : α) × β) := ⟨p.fst, p.snd⟩ + +@[simp] +theorem Prod.fst_comp_toSigma : + Sigma.fst ∘ Prod.toSigma = @Prod.fst α β := by + apply funext + simp [Prod.toSigma] + +/-- Internal implementation detail of the hash map -/ +def insertListConst [BEq α] (l : List ((_ : α) × β)) (toInsert : List (α × β)) : List ((_ : α) × β) := + insertList l (toInsert.map Prod.toSigma) + +theorem containsKey_insertListConst [BEq α] [PartialEquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} {k : α} : + containsKey k (insertListConst l toInsert) = + (containsKey k l || (toInsert.map Prod.fst).contains k) := by + unfold insertListConst + rw [containsKey_insertList] + simp + +theorem containsKey_of_containsKey_insertListConst [BEq α] [PartialEquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} {k : α} + (h₁ : containsKey k (insertListConst l toInsert)) + (h₂ : (toInsert.map Prod.fst).contains k = false) : containsKey k l := by + unfold insertListConst at h₁ + apply containsKey_of_containsKey_insertList h₁ + simpa + +theorem getKey?_insertListConst_of_contains_eq_false [BEq α] [EquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} {k : α} + (not_contains : (toInsert.map Prod.fst).contains k = false) : + getKey? k (insertListConst l toInsert) = getKey? k l := by + unfold insertListConst + apply getKey?_insertList_of_contains_eq_false + simpa + +theorem getKey?_insertListConst_of_mem [BEq α] [EquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ toInsert.map Prod.fst) : + getKey? k' (insertListConst l toInsert) = some k := by + unfold insertListConst + apply getKey?_insertList_of_mem k_beq distinct_l + · simpa [List.pairwise_map] + · simp only [List.map_map, Prod.fst_comp_toSigma] + exact mem + +theorem getKey_insertListConst_of_contains_eq_false [BEq α] [EquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} {k : α} + (not_contains : (toInsert.map Prod.fst).contains k = false) + {h} : + getKey k (insertListConst l toInsert) h = + getKey k l (containsKey_of_containsKey_insertListConst h not_contains) := by + rw [← Option.some_inj, ← getKey?_eq_some_getKey, + getKey?_insertListConst_of_contains_eq_false not_contains, getKey?_eq_some_getKey] + +theorem getKey_insertListConst_of_mem [BEq α] [EquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ toInsert.map Prod.fst) + {h} : + getKey k' (insertListConst l toInsert) h = k := by + rw [← Option.some_inj, ← getKey?_eq_some_getKey, + getKey?_insertListConst_of_mem k_beq distinct_l distinct_toInsert mem] + +theorem getKey!_insertListConst_of_contains_eq_false [BEq α] [EquivBEq α] [Inhabited α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} {k : α} + (not_contains : (toInsert.map Prod.fst).contains k = false) : + getKey! k (insertListConst l toInsert) = getKey! k l := by + rw [getKey!_eq_getKey?, getKey?_insertListConst_of_contains_eq_false not_contains, + getKey!_eq_getKey?] + +theorem getKey!_insertListConst_of_mem [BEq α] [EquivBEq α] [Inhabited α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ toInsert.map Prod.fst) : + getKey! k' (insertListConst l toInsert) = k := by + rw [getKey!_eq_getKey?, getKey?_insertListConst_of_mem k_beq distinct_l distinct_toInsert mem, + Option.get!_some] + +theorem getKeyD_insertListConst_of_contains_eq_false [BEq α] [EquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} {k fallback : α} + (not_contains : (toInsert.map Prod.fst).contains k = false) : + getKeyD k (insertListConst l toInsert) fallback = getKeyD k l fallback := by + rw [getKeyD_eq_getKey?, getKey?_insertListConst_of_contains_eq_false not_contains, + getKeyD_eq_getKey?] + +theorem getKeyD_insertListConst_of_mem [BEq α] [EquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} + {k k' fallback : α} (k_beq : k == k') + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ toInsert.map Prod.fst) : + getKeyD k' (insertListConst l toInsert) fallback = k := by + rw [getKeyD_eq_getKey?, getKey?_insertListConst_of_mem k_beq distinct_l distinct_toInsert mem, + Option.getD_some] + +theorem length_insertListConst [BEq α] [EquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (distinct_both : ∀ (a : α), containsKey a l → (toInsert.map Prod.fst).contains a = false) : + (insertListConst l toInsert).length = l.length + toInsert.length := by + unfold insertListConst + rw [length_insertList distinct_l] + · simp + · simpa [List.pairwise_map] + · simpa using distinct_both + +theorem length_le_length_insertListConst [BEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} : + l.length ≤ (insertListConst l toInsert).length := by + induction toInsert generalizing l with + | nil => apply Nat.le_refl + | cons hd tl ih => exact Nat.le_trans length_le_length_insertEntry ih + +theorem length_insertListConst_le [BEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} : + (insertListConst l toInsert).length ≤ l.length + toInsert.length := by + unfold insertListConst + rw [← List.length_map toInsert Prod.toSigma] + apply length_insertList_le + +theorem isEmpty_insertListConst [BEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} : + (List.insertListConst l toInsert).isEmpty = (l.isEmpty && toInsert.isEmpty) := by + unfold insertListConst + rw [isEmpty_insertList, Bool.eq_iff_iff] + simp + +theorem getValue?_insertListConst_of_contains_eq_false [BEq α] [PartialEquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} {k : α} + (not_contains : (toInsert.map Prod.fst).contains k = false) : + getValue? k (insertListConst l toInsert) = getValue? k l := by + unfold insertListConst + rw [getValue?_eq_getEntry?, getValue?_eq_getEntry?, getEntry?_insertList_of_contains_eq_false] + rw [containsKey_eq_contains_map_fst] + simpa + +theorem getValue?_insertListConst_of_mem [BEq α] [EquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} + {k k' : α} (k_beq : k == k') {v : β} + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ toInsert) : + getValue? k' (insertListConst l toInsert) = v := by + unfold insertListConst + rw [getValue?_eq_getEntry?] + have : getEntry? k' (insertList l (toInsert.map Prod.toSigma)) = + getEntry? k' (toInsert.map Prod.toSigma) := by + apply getEntry?_insertList_of_contains_eq_true distinct_l (by simpa [List.pairwise_map]) + apply containsKey_of_beq _ k_beq + rw [containsKey_eq_contains_map_fst, List.map_map, Prod.fst_comp_toSigma, + List.contains_iff_exists_mem_beq] + exists k + rw [List.mem_map] + constructor + . exists ⟨k, v⟩ + . simp + rw [this] + rw [getEntry?_of_mem _ k_beq _] + . rfl + · simpa [DistinctKeys.def, List.pairwise_map] + . simp only [List.mem_map] + exists (k, v) + +theorem getValue_insertListConst_of_contains_eq_false [BEq α] [PartialEquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} {k : α} + {not_contains : (toInsert.map Prod.fst).contains k = false} + {h} : + getValue k (insertListConst l toInsert) h = + getValue k l (containsKey_of_containsKey_insertListConst h not_contains) := by + rw [← Option.some_inj, ← getValue?_eq_some_getValue, ← getValue?_eq_some_getValue, + getValue?_insertListConst_of_contains_eq_false not_contains] + +theorem getValue_insertListConst_of_mem [BEq α] [EquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} + {k k' : α} (k_beq : k == k') {v : β} + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ toInsert) + {h} : + getValue k' (insertListConst l toInsert) h = v := by + rw [← Option.some_inj, ← getValue?_eq_some_getValue, + getValue?_insertListConst_of_mem k_beq distinct_l distinct_toInsert mem] + +theorem getValue!_insertListConst_of_contains_eq_false [BEq α] [PartialEquivBEq α] [Inhabited β] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} {k : α} + (not_contains : (toInsert.map Prod.fst).contains k = false) : + getValue! k (insertListConst l toInsert) = getValue! k l := by + simp only [getValue!_eq_getValue?] + rw [getValue?_insertListConst_of_contains_eq_false not_contains] + +theorem getValue!_insertListConst_of_mem [BEq α] [EquivBEq α] [Inhabited β] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} {k k' : α} {v: β} (k_beq : k == k') + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ toInsert): + getValue! k' (insertListConst l toInsert) = v := by + rw [getValue!_eq_getValue?, + getValue?_insertListConst_of_mem k_beq distinct_l distinct_toInsert mem, Option.get!_some] + +theorem getValueD_insertListConst_of_contains_eq_false [BEq α] [PartialEquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} {k : α} {fallback : β} + (not_contains : (toInsert.map Prod.fst).contains k = false) : + getValueD k (insertListConst l toInsert) fallback = getValueD k l fallback := by + simp only [getValueD_eq_getValue?] + rw [getValue?_insertListConst_of_contains_eq_false not_contains] + +theorem getValueD_insertListConst_of_mem [BEq α] [EquivBEq α] + {l : List ((_ : α) × β)} {toInsert : List (α × β)} {k k' : α} {v fallback: β} (k_beq : k == k') + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ toInsert): + getValueD k' (insertListConst l toInsert) fallback= v := by + simp only [getValueD_eq_getValue?] + rw [getValue?_insertListConst_of_mem k_beq distinct_l distinct_toInsert mem, Option.getD_some] + +/-- Internal implementation detail of the hash map -/ +def insertListIfNewUnit [BEq α] (l: List ((_ : α) × Unit)) (toInsert: List α) : + List ((_ : α) × Unit) := + match toInsert with + | .nil => l + | .cons hd tl => insertListIfNewUnit (insertEntryIfNew hd () l) tl + +theorem insertListIfNewUnit_perm_of_perm_first [BEq α] [EquivBEq α] {l1 l2 : List ((_ : α) × Unit)} + {toInsert : List α } (h : Perm l1 l2) (distinct : DistinctKeys l1) : + Perm (insertListIfNewUnit l1 toInsert) (insertListIfNewUnit l2 toInsert) := by + induction toInsert generalizing l1 l2 with + | nil => simp [insertListIfNewUnit, h] + | cons hd tl ih => + simp only [insertListIfNewUnit] + apply ih + · simp only [insertEntryIfNew, cond_eq_if] + have contains_eq : containsKey hd l1 = containsKey hd l2 := containsKey_of_perm h + rw [contains_eq] + by_cases contains_hd: containsKey hd l2 = true + · simp only [contains_hd, ↓reduceIte] + exact h + · simp only [contains_hd, Bool.false_eq_true, ↓reduceIte, List.perm_cons] + exact h + · apply DistinctKeys.insertEntryIfNew distinct + +theorem DistinctKeys.insertListIfNewUnit [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × Unit)} + {toInsert : List α} (distinct: DistinctKeys l): + DistinctKeys (insertListIfNewUnit l toInsert) := by + induction toInsert generalizing l with + | nil => simp [List.insertListIfNewUnit, distinct] + | cons hd tl ih => + simp only [List.insertListIfNewUnit] + apply ih (insertEntryIfNew distinct) + +theorem getEntry?_insertListIfNewUnit [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × Unit)} + {toInsert : List α} {k : α} : + getEntry? k (insertListIfNewUnit l toInsert) = + (getEntry? k l).or (getEntry? k (toInsert.map (⟨·, ()⟩))) := by + induction toInsert generalizing l with + | nil => simp [insertListIfNewUnit] + | cons hd tl ih => + simp only [insertListIfNewUnit, ih, getEntry?_insertEntryIfNew, List.map_cons, + getEntry?_cons] + cases hhd : hd == k + · simp + · cases hc : containsKey hd l + · simp only [Bool.not_false, Bool.and_self, ↓reduceIte, Option.some_or, cond_true, + Option.or_some', Option.some.injEq] + rw [getEntry?_eq_none.2, Option.getD_none] + rwa [← containsKey_congr hhd] + · simp only [Bool.not_true, Bool.and_false, Bool.false_eq_true, ↓reduceIte, cond_true, + Option.or_some', getEntry?_eq_none] + rw [containsKey_congr hhd, containsKey_eq_isSome_getEntry?] at hc + obtain ⟨v, hv⟩ := Option.isSome_iff_exists.1 hc + simp [hv] + +theorem DistinctKeys.mapUnit [BEq α] + {l : List α} (distinct: l.Pairwise (fun a b => (a == b) = false)) : + DistinctKeys (l.map (⟨·, ()⟩)) := by + rw [DistinctKeys.def] + refine List.Pairwise.map ?_ ?_ distinct + simp + +theorem getEntry?_insertListIfNewUnit_of_contains_eq_false [BEq α] [PartialEquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α } {k : α} + (not_contains : toInsert.contains k = false) : + getEntry? k (insertListIfNewUnit l toInsert) = getEntry? k l := by + induction toInsert generalizing l with + | nil => simp [insertListIfNewUnit] + | cons h t ih => + unfold insertListIfNewUnit + simp only [List.contains_cons, Bool.or_eq_false_iff] at not_contains + rw [ih not_contains.right, getEntry?_insertEntryIfNew] + simp only [Bool.and_eq_true, Bool.not_eq_eq_eq_not, Bool.not_true, ite_eq_right_iff, and_imp] + intro h' + rw [BEq.comm, And.left not_contains] at h' + simp at h' + +theorem containsKey_insertListIfNewUnit [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × Unit)} + {toInsert : List α} {k : α} : + containsKey k (insertListIfNewUnit l toInsert) = (containsKey k l || toInsert.contains k) := by + induction toInsert generalizing l with + | nil => simp [insertListIfNewUnit] + | cons hd tl ih => + simp only [insertListIfNewUnit, List.contains_cons] + rw [ih, containsKey_insertEntryIfNew] + rw [Bool.or_comm (hd == k), Bool.or_assoc, BEq.comm (a:=hd)] + +theorem containsKey_of_containsKey_insertListIfNewUnit [BEq α] [PartialEquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α} {k : α} + (h₂ : toInsert.contains k = false) : containsKey k (insertListIfNewUnit l toInsert) → + containsKey k l := by + intro h₁ + rw [containsKey_insertListIfNewUnit, h₂] at h₁; simp at h₁; exact h₁ + +theorem getKey?_insertListIfNewUnit_of_contains_eq_false_of_contains_eq_false [BEq α] [EquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α} {k : α} + (h': containsKey k l = false) (h : toInsert.contains k = false) : + getKey? k (insertListIfNewUnit l toInsert) = none := by + rw [getKey?_eq_getEntry?, + getEntry?_insertListIfNewUnit_of_contains_eq_false h, Option.map_eq_none', getEntry?_eq_none] + exact h' + +theorem getKey?_insertListIfNewUnit_of_contains_eq_false_of_mem [BEq α] [EquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α} + {k k' : α} (k_beq : k == k') + (mem' : containsKey k l = false) + (distinct : toInsert.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ toInsert): + getKey? k' (insertListIfNewUnit l toInsert) = some k := by + simp only [getKey?_eq_getEntry?, getEntry?_insertListIfNewUnit, Option.map_eq_some', + Option.or_eq_some, getEntry?_eq_none] + exists ⟨k, ()⟩ + simp only [and_true] + right + constructor + · rw [containsKey_congr k_beq] at mem' + exact mem' + · apply getEntry?_of_mem (DistinctKeys.mapUnit distinct) k_beq + simp only [List.mem_map] + exists k + +theorem getKey?_insertListIfNewUnit_of_contains [BEq α] [EquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α} + {k : α} + (h : containsKey k l = true): + getKey? k (insertListIfNewUnit l toInsert) = getKey? k l := by + rw [containsKey_eq_isSome_getEntry?] at h + simp [getKey?_eq_getEntry?, getEntry?_insertListIfNewUnit, Option.or_of_isSome h] + +theorem getKey_insertListIfNewUnit_of_contains_eq_false_of_mem [BEq α] [EquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α} + {k k' : α} (k_beq : k == k') + {h} (contains_eq_false : containsKey k l = false) + (distinct : toInsert.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ toInsert) : + getKey k' (insertListIfNewUnit l toInsert) h = k := by + rw [← Option.some_inj, ← getKey?_eq_some_getKey, + getKey?_insertListIfNewUnit_of_contains_eq_false_of_mem k_beq contains_eq_false distinct mem] + +theorem getKey_insertListIfNewUnit_of_contains [BEq α] [EquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α} + {k : α} + (contains : containsKey k l = true) {h}: + getKey k (insertListIfNewUnit l toInsert) h = getKey k l contains := by + rw [← Option.some_inj, ← getKey?_eq_some_getKey, ← getKey?_eq_some_getKey, + getKey?_insertListIfNewUnit_of_contains contains] + +theorem getKey!_insertListIfNewUnit_of_contains_eq_false_of_contains_eq_false [BEq α] [EquivBEq α] + [Inhabited α] {l : List ((_ : α) × Unit)} {toInsert : List α} {k : α} + (contains_eq_false : containsKey k l = false) + (contains_eq_false' : toInsert.contains k = false) : + getKey! k (insertListIfNewUnit l toInsert) = default := by + rw [getKey!_eq_getKey?, getKey?_insertListIfNewUnit_of_contains_eq_false_of_contains_eq_false + contains_eq_false contains_eq_false'] + simp + +theorem getKey!_insertListIfNewUnit_of_contains_eq_false_of_mem [BEq α] [EquivBEq α] [Inhabited α] + {l : List ((_ : α) × Unit)} {toInsert : List α} + {k k' : α} (k_beq : k == k') + (h : containsKey k l = false) + (distinct : toInsert.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ toInsert) : + getKey! k' (insertListIfNewUnit l toInsert) = k := by + rw [getKey!_eq_getKey?, + getKey?_insertListIfNewUnit_of_contains_eq_false_of_mem k_beq h distinct mem, Option.get!_some] + +theorem getKey!_insertListIfNewUnit_of_contains [BEq α] [EquivBEq α] [Inhabited α] + {l : List ((_ : α) × Unit)} {toInsert : List α} + {k : α} + (h : containsKey k l = true) : + getKey! k (insertListIfNewUnit l toInsert) = getKey! k l := by + rw [getKey!_eq_getKey?, getKey?_insertListIfNewUnit_of_contains h, getKey!_eq_getKey?] + +theorem getKeyD_insertListIfNewUnit_of_contains_eq_false_of_contains_eq_false [BEq α] [EquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α} {k fallback : α} + (contains_eq_false : containsKey k l = false) (contains_eq_false' : toInsert.contains k = false) : + getKeyD k (insertListIfNewUnit l toInsert) fallback = fallback := by + rw [getKeyD_eq_getKey?, getKey?_insertListIfNewUnit_of_contains_eq_false_of_contains_eq_false + contains_eq_false contains_eq_false'] + simp + +theorem getKeyD_insertListIfNewUnit_of_contains_eq_false_of_mem [BEq α] [EquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α} + {k k' fallback : α} (k_beq : k == k') + (h : containsKey k l = false) + (distinct : toInsert.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ toInsert) : + getKeyD k' (insertListIfNewUnit l toInsert) fallback = k := by + rw [getKeyD_eq_getKey?, getKey?_insertListIfNewUnit_of_contains_eq_false_of_mem k_beq h + distinct mem, Option.getD_some] + +theorem getKeyD_insertListIfNewUnit_of_contains [BEq α] [EquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α} + {k fallback : α} + (contains : containsKey k l = true) : + getKeyD k (insertListIfNewUnit l toInsert) fallback = getKeyD k l fallback := by + rw [getKeyD_eq_getKey?, + getKey?_insertListIfNewUnit_of_contains contains, getKeyD_eq_getKey?] + +theorem length_insertListIfNewUnit [BEq α] [EquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α} + (distinct_l : DistinctKeys l) + (distinct_toInsert : toInsert.Pairwise (fun a b => (a == b) = false)) + (distinct_both : ∀ (a : α), containsKey a l → toInsert.contains a = false) : + (insertListIfNewUnit l toInsert).length = l.length + toInsert.length := by + induction toInsert generalizing l with + | nil => simp [insertListIfNewUnit] + | cons hd tl ih => + simp only [insertListIfNewUnit, List.length_cons] + rw [ih] + · rw [length_insertEntryIfNew] + specialize distinct_both hd + simp only [List.contains_cons, BEq.refl, Bool.true_or, and_true, + Bool.not_eq_true] at distinct_both + cases eq : containsKey hd l with + | true => simp [eq] at distinct_both + | false => + simp only [Bool.false_eq_true, ↓reduceIte] + rw [Nat.add_assoc, Nat.add_comm 1 _] + · apply DistinctKeys.insertEntryIfNew distinct_l + · simp only [pairwise_cons] at distinct_toInsert + apply And.right distinct_toInsert + · intro a + simp only [List.contains_cons, Bool.or_eq_true, not_and, not_or, + Bool.not_eq_true] at distinct_both + rw [containsKey_insertEntryIfNew] + simp only [Bool.or_eq_true] + intro h + cases h with + | inl h => + simp only [pairwise_cons] at distinct_toInsert + rw [List.contains_eq_any_beq] + simp only [List.any_eq_false, Bool.not_eq_true] + intro x x_mem + rcases distinct_toInsert with ⟨left,_⟩ + specialize left x x_mem + apply BEq.neq_of_beq_of_neq + apply BEq.symm h + exact left + | inr h => + specialize distinct_both a h + rw [Bool.or_eq_false_iff] at distinct_both + apply And.right distinct_both + +theorem length_le_length_insertListIfNewUnit [BEq α] [EquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α}: + l.length ≤ (insertListIfNewUnit l toInsert).length := by + induction toInsert generalizing l with + | nil => apply Nat.le_refl + | cons hd tl ih => exact Nat.le_trans length_le_length_insertEntryIfNew ih + +theorem length_insertListIfNewUnit_le [BEq α] [EquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α}: + (insertListIfNewUnit l toInsert).length ≤ l.length + toInsert.length := by + induction toInsert generalizing l with + | nil => simp only [insertListIfNewUnit, List.length_nil, Nat.add_zero, Nat.le_refl] + | cons hd tl ih => + simp only [insertListIfNewUnit, List.length_cons] + apply Nat.le_trans ih + rw [Nat.add_comm tl.length 1, ← Nat.add_assoc] + apply Nat.add_le_add _ (Nat.le_refl _) + apply length_insertEntryIfNew_le + +theorem isEmpty_insertListIfNewUnit [BEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α} : + (List.insertListIfNewUnit l toInsert).isEmpty = (l.isEmpty && toInsert.isEmpty) := by + induction toInsert generalizing l with + | nil => simp [insertListIfNewUnit] + | cons hd tl ih => + rw [insertListIfNewUnit, List.isEmpty_cons, ih, isEmpty_insertEntryIfNew] + simp + +theorem getValue?_list_unit [BEq α] {l : List ((_ : α) × Unit)} {k : α}: + getValue? k l = if containsKey k l = true then some () else none := by + induction l with + | nil => simp + | cons hd tl ih => + simp only [getValue?, containsKey, Bool.or_eq_true, Bool.cond_eq_ite_iff] + by_cases hd_k: (hd.fst == k) = true + · simp [hd_k] + · simp [hd_k, ih] + +theorem getValue?_insertListIfNewUnit [BEq α] [PartialEquivBEq α] + {l : List ((_ : α) × Unit)} {toInsert : List α} {k : α}: + getValue? k (insertListIfNewUnit l toInsert) = + if containsKey k l ∨ toInsert.contains k then some () else none := by + simp [containsKey_insertListIfNewUnit, getValue?_list_unit] + +end + /-- Internal implementation detail of the hash map -/ def alterKey [BEq α] [LawfulBEq α] (k : α) (f : Option (β k) → Option (β k)) (l : List ((a : α) × β a)) : List ((a : α) × β a) := diff --git a/src/Std/Data/DHashMap/Internal/Model.lean b/src/Std/Data/DHashMap/Internal/Model.lean index 8384a6976db0..4020b4a31011 100644 --- a/src/Std/Data/DHashMap/Internal/Model.lean +++ b/src/Std/Data/DHashMap/Internal/Model.lean @@ -201,7 +201,7 @@ theorem toListModel_updateAllBuckets {m : Raw₀ α β} {f : AssocList α β → omega rw [updateAllBuckets, toListModel, Array.toList_map, List.flatMap_eq_foldl, List.foldl_map, toListModel, List.flatMap_eq_foldl] - suffices ∀ (l : List (AssocList α β)) (l' : List ((a: α) × δ a)) (l'' : List ((a : α) × β a)), + suffices ∀ (l : List (AssocList α β)) (l' : List ((a : α) × δ a)) (l'' : List ((a : α) × β a)), Perm (g l'') l' → Perm (l.foldl (fun acc a => acc ++ (f a).toList) l') (g (l.foldl (fun acc a => acc ++ a.toList) l'')) by @@ -378,6 +378,12 @@ def mapₘ (m : Raw₀ α β) (f : (a : α) → β a → δ a) : Raw₀ α δ := def filterₘ (m : Raw₀ α β) (f : (a : α) → β a → Bool) : Raw₀ α β := ⟨withComputedSize (updateAllBuckets m.1.buckets fun l => l.filter f), by simpa using m.2⟩ +/-- Internal implementation detail of the hash map -/ +def insertListₘ [BEq α] [Hashable α] (m : Raw₀ α β) (l : List ((a : α) × β a)) : Raw₀ α β := + match l with + | .nil => m + | .cons hd tl => insertListₘ (m.insert hd.1 hd.2) tl + section variable {β : Type v} @@ -398,6 +404,20 @@ def Const.getDₘ [BEq α] [Hashable α] (m : Raw₀ α (fun _ => β)) (a : α) def Const.get!ₘ [BEq α] [Hashable α] [Inhabited β] (m : Raw₀ α (fun _ => β)) (a : α) : β := (Const.get?ₘ m a).get! +/-- Internal implementation detail of the hash map -/ +def Const.insertListₘ [BEq α] [Hashable α] (m : Raw₀ α (fun _ => β)) (l: List (α × β)) : + Raw₀ α (fun _ => β) := + match l with + | .nil => m + | .cons hd tl => insertListₘ (m.insert hd.1 hd.2) tl + +/-- Internal implementation detail of the hash map -/ +def Const.insertListIfNewUnitₘ [BEq α] [Hashable α] (m : Raw₀ α (fun _ => Unit)) (l: List α) : + Raw₀ α (fun _ => Unit) := + match l with + | .nil => m + | .cons hd tl => insertListIfNewUnitₘ (m.insertIfNew hd ()) tl + end /-! # Equivalence between model functions and real implementations -/ @@ -569,6 +589,19 @@ theorem map_eq_mapₘ (m : Raw₀ α β) (f : (a : α) → β a → δ a) : theorem filter_eq_filterₘ (m : Raw₀ α β) (f : (a : α) → β a → Bool) : m.filter f = m.filterₘ f := rfl +theorem insertMany_eq_insertListₘ [BEq α] [Hashable α](m : Raw₀ α β) (l : List ((a : α) × β a)) : insertMany m l = insertListₘ m l := by + simp only [insertMany, Id.run, Id.pure_eq, Id.bind_eq, List.forIn_yield_eq_foldl] + suffices ∀ (t : { m' // ∀ (P : Raw₀ α β → Prop), + (∀ {m'' : Raw₀ α β} {a : α} {b : β a}, P m'' → P (m''.insert a b)) → P m → P m' }), + (List.foldl (fun m' p => ⟨m'.val.insert p.1 p.2, fun P h₁ h₂ => h₁ (m'.2 _ h₁ h₂)⟩) t l).val = + t.val.insertListₘ l from this _ + intro t + induction l generalizing m with + | nil => simp [insertListₘ] + | cons hd tl ih => + simp only [List.foldl_cons, insertListₘ] + apply ih + section variable {β : Type v} @@ -599,6 +632,36 @@ theorem Const.getThenInsertIfNew?_eq_get?ₘ [BEq α] [Hashable α] (m : Raw₀ dsimp only [Array.ugetElem_eq_getElem, Array.uset] split <;> simp_all [-getValue?_eq_none] +theorem Const.insertMany_eq_insertListₘ [BEq α] [Hashable α] (m : Raw₀ α (fun _ => β)) + (l: List (α × β)): + (Const.insertMany m l).1 = Const.insertListₘ m l := by + simp only [insertMany, Id.run, Id.pure_eq, Id.bind_eq, List.forIn_yield_eq_foldl] + suffices ∀ (t : { m' // ∀ (P : Raw₀ α (fun _ => β) → Prop), + (∀ {m'' : Raw₀ α (fun _ => β)} {a : α} {b : β}, P m'' → P (m''.insert a b)) → P m → P m' }), + (List.foldl (fun m' p => ⟨m'.val.insert p.1 p.2, fun P h₁ h₂ => h₁ (m'.2 _ h₁ h₂)⟩) t l).val = + Const.insertListₘ t.val l from this _ + intro t + induction l generalizing m with + | nil => simp [insertListₘ] + | cons hd tl ih => + simp only [List.foldl_cons, insertListₘ] + apply ih + +theorem Const.insertManyIfNewUnit_eq_insertListIfNewUnitₘ [BEq α] [Hashable α] + (m : Raw₀ α (fun _ => Unit)) (l: List α): + (Const.insertManyIfNewUnit m l).1 = Const.insertListIfNewUnitₘ m l := by + simp only [insertManyIfNewUnit, Id.run, Id.pure_eq, Id.bind_eq, List.forIn_yield_eq_foldl] + suffices ∀ (t : { m' // ∀ (P : Raw₀ α (fun _ => Unit) → Prop), + (∀ {m'' a b}, P m'' → P (m''.insertIfNew a b)) → P m → P m'}), + (List.foldl (fun m' p => ⟨m'.val.insertIfNew p (), fun P h₁ h₂ => h₁ (m'.2 _ h₁ h₂)⟩) t l).val = + Const.insertListIfNewUnitₘ t.val l from this _ + intro t + induction l generalizing m with + | nil => simp [insertListIfNewUnitₘ] + | cons hd tl ih => + simp only [List.foldl_cons, insertListIfNewUnitₘ] + apply ih + end end Raw₀ diff --git a/src/Std/Data/DHashMap/Internal/Raw.lean b/src/Std/Data/DHashMap/Internal/Raw.lean index 810804db8e75..4b28a7153eae 100644 --- a/src/Std/Data/DHashMap/Internal/Raw.lean +++ b/src/Std/Data/DHashMap/Internal/Raw.lean @@ -199,10 +199,52 @@ theorem filter_val [BEq α] [Hashable α] {m : Raw₀ α β} {f : (a : α) → m.val.filter f = m.filter f := by simp [Raw.filter, m.2] +theorem insertMany_eq [BEq α] [Hashable α] {m : Raw α β} (h : m.WF) {ρ : Type w} [ForIn Id ρ ((a : α) × β a)] {l : ρ} : + m.insertMany l = Raw₀.insertMany ⟨m, h.size_buckets_pos⟩ l := by + simp [Raw.insertMany, h.size_buckets_pos] + +theorem insertMany_val [BEq α][Hashable α] {m : Raw₀ α β} {ρ : Type w} [ForIn Id ρ ((a : α) × β a)] {l : ρ} : + m.val.insertMany l = m.insertMany l := by + simp [Raw.insertMany, m.2] + +theorem ofList_eq [BEq α] [Hashable α] {l : List ((a : α) × β a)} : + Raw.ofList l = Raw₀.insertMany Raw₀.empty l := by + simp only [Raw.ofList, Raw.insertMany, (Raw.WF.empty).size_buckets_pos ∅, ↓reduceDIte] + congr + section variable {β : Type v} +theorem Const.insertMany_eq [BEq α] [Hashable α] {m : Raw α (fun _ => β)} (h : m.WF) {ρ : Type w} [ForIn Id ρ (α × β)] {l : ρ} : + Raw.Const.insertMany m l = Raw₀.Const.insertMany ⟨m, h.size_buckets_pos⟩ l := by + simp [Raw.Const.insertMany, h.size_buckets_pos] + +theorem Const.insertMany_val [BEq α][Hashable α] {m : Raw₀ α (fun _ => β)} {ρ : Type w} [ForIn Id ρ (α × β)] {l : ρ} : + Raw.Const.insertMany m.val l = Raw₀.Const.insertMany m l := by + simp [Raw.Const.insertMany, m.2] + +theorem Const.ofList_eq [BEq α] [Hashable α] {l : List (α × β)} : + Raw.Const.ofList l = Raw₀.Const.insertMany Raw₀.empty l := by + simp only [Raw.Const.ofList, Raw.Const.insertMany, (Raw.WF.empty).size_buckets_pos ∅, ↓reduceDIte] + congr + +theorem Const.insertManyIfNewUnit_eq {ρ : Type w} [ForIn Id ρ α] [BEq α] [Hashable α] + {m : Raw α (fun _ => Unit)} {l : ρ} (h : m.WF): + Raw.Const.insertManyIfNewUnit m l = Raw₀.Const.insertManyIfNewUnit ⟨m, h.size_buckets_pos⟩ l := by + simp [Raw.Const.insertManyIfNewUnit, h.size_buckets_pos] + +theorem Const.insertManyIfNewUnit_val {ρ : Type w} [ForIn Id ρ α] [BEq α] [Hashable α] + {m : Raw₀ α (fun _ => Unit)} {l : ρ} : + Raw.Const.insertManyIfNewUnit m.val l = Raw₀.Const.insertManyIfNewUnit m l := by + simp [Raw.Const.insertManyIfNewUnit, m.2] + +theorem Const.unitOfList_eq [BEq α] [Hashable α] {l : List α} : + Raw.Const.unitOfList l = Raw₀.Const.insertManyIfNewUnit Raw₀.empty l := by + simp only [Raw.Const.unitOfList, Raw.Const.insertManyIfNewUnit, (Raw.WF.empty).size_buckets_pos ∅, + ↓reduceDIte] + congr + theorem Const.get?_eq [BEq α] [Hashable α] {m : Raw α (fun _ => β)} (h : m.WF) {a : α} : Raw.Const.get? m a = Raw₀.Const.get? ⟨m, h.size_buckets_pos⟩ a := by simp [Raw.Const.get?, h.size_buckets_pos] diff --git a/src/Std/Data/DHashMap/Internal/RawLemmas.lean b/src/Std/Data/DHashMap/Internal/RawLemmas.lean index 60343ea5fbac..f04f9403231d 100644 --- a/src/Std/Data/DHashMap/Internal/RawLemmas.lean +++ b/src/Std/Data/DHashMap/Internal/RawLemmas.lean @@ -70,9 +70,10 @@ variable [BEq α] [Hashable α] /-- Internal implementation detail of the hash map -/ scoped macro "wf_trivial" : tactic => `(tactic| repeat (first - | apply Raw₀.wfImp_insert | apply Raw₀.wfImp_insertIfNew | apply Raw₀.wfImp_erase - | apply Raw.WF.out | assumption | apply Raw₀.wfImp_empty | apply Raw.WFImp.distinct - | apply Raw.WF.empty₀)) + | apply Raw₀.wfImp_insert | apply Raw₀.wfImp_insertIfNew | apply Raw₀.wfImp_insertMany + | apply Raw₀.Const.wfImp_insertMany| apply Raw₀.Const.wfImp_insertManyIfNewUnit + | apply Raw₀.wfImp_erase | apply Raw.WF.out | assumption | apply Raw₀.wfImp_empty + | apply Raw.WFImp.distinct | apply Raw.WF.empty₀)) /-- Internal implementation detail of the hash map -/ scoped macro "empty" : tactic => `(tactic| { intros; simp_all [List.isEmpty_iff] } ) @@ -90,7 +91,9 @@ private def queryNames : Array Name := ``Raw.pairwise_keys_iff_pairwise_keys] private def modifyNames : Array Name := - #[``toListModel_insert, ``toListModel_erase, ``toListModel_insertIfNew] + #[``toListModel_insert, ``toListModel_erase, ``toListModel_insertIfNew, + ``toListModel_insertMany_list, ``Const.toListModel_insertMany_list, + ``Const.toListModel_insertManyIfNewUnit_list] private def congrNames : MacroM (Array (TSyntax `term)) := do return #[← `(_root_.List.Perm.isEmpty_eq), ← `(containsKey_of_perm), @@ -820,8 +823,8 @@ theorem length_keys [EquivBEq α] [LawfulHashable α] (h : m.1.WF) : simp_to_model using List.length_keys_eq_length @[simp] -theorem isEmpty_keys [EquivBEq α] [LawfulHashable α] (h: m.1.WF): - m.1.keys.isEmpty = m.1.isEmpty:= by +theorem isEmpty_keys [EquivBEq α] [LawfulHashable α] (h : m.1.WF) : + m.1.keys.isEmpty = m.1.isEmpty := by simp_to_model using List.isEmpty_keys_eq_isEmpty @[simp] @@ -839,6 +842,884 @@ theorem distinct_keys [EquivBEq α] [LawfulHashable α] (h : m.1.WF) : m.1.keys.Pairwise (fun a b => (a == b) = false) := by simp_to_model using (Raw.WF.out h).distinct.distinct +@[simp] +theorem insertMany_nil : + m.insertMany [] = m := by + simp [insertMany, Id.run] + +@[simp] +theorem insertMany_list_singleton {k : α} {v : β k} : + m.insertMany [⟨k, v⟩] = m.insert k v := by + simp [insertMany, Id.run] + +theorem insertMany_cons {l : List ((a : α) × β a)} {k : α} {v : β k} : + (m.insertMany (⟨k, v⟩ :: l)).1 = ((m.insert k v).insertMany l).1 := by + simp only [insertMany_eq_insertListₘ] + cases l with + | nil => simp [insertListₘ] + | cons hd tl => simp [insertListₘ] + +@[simp] +theorem contains_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k : α} : + (m.insertMany l).1.contains k = (m.contains k || (l.map Sigma.fst).contains k) := by + simp_to_model using List.containsKey_insertList + +theorem contains_of_contains_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k : α} : + (m.insertMany l).1.contains k → (l.map Sigma.fst).contains k = false → m.contains k := by + simp_to_model using List.containsKey_of_containsKey_insertList + +theorem get?_insertMany_list_of_contains_eq_false [LawfulBEq α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k : α} + (h' : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).1.get? k = m.get? k := by + simp_to_model using getValueCast?_insertList_of_contains_eq_false + +theorem get?_insertMany_list_of_mem [LawfulBEq α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (m.insertMany l).1.get? k' = some (cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v) := by + simp_to_model using getValueCast?_insertList_of_mem + +theorem get_insertMany_list_of_contains_eq_false [LawfulBEq α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k : α} + (contains : (l.map Sigma.fst).contains k = false) + {h'} : + (m.insertMany l).1.get k h' = + m.get k (contains_of_contains_insertMany_list _ h h' contains) := by + simp_to_model using getValueCast_insertList_of_contains_eq_false + +theorem get_insertMany_list_of_mem [LawfulBEq α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) + {h'} : + (m.insertMany l).1.get k' h' = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := by + simp_to_model using getValueCast_insertList_of_mem + +theorem get!_insertMany_list_of_contains_eq_false [LawfulBEq α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k : α} [Inhabited (β k)] + (h' : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).1.get! k = m.get! k := by + simp_to_model using getValueCast!_insertList_of_contains_eq_false + +theorem get!_insertMany_list_of_mem [LawfulBEq α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} [Inhabited (β k')] + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (m.insertMany l).1.get! k' = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := by + simp_to_model using getValueCast!_insertList_of_mem + +theorem getD_insertMany_list_of_contains_eq_false [LawfulBEq α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k : α} {fallback : β k} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).1.getD k fallback = m.getD k fallback := by + simp_to_model using getValueCastD_insertList_of_contains_eq_false + +theorem getD_insertMany_list_of_mem [LawfulBEq α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} {fallback : β k'} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (m.insertMany l).1.getD k' fallback = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := by + simp_to_model using getValueCastD_insertList_of_mem + +theorem getKey?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k : α} + (h' : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).1.getKey? k = m.getKey? k := by + simp_to_model using getKey?_insertList_of_contains_eq_false + +theorem getKey?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (m.insertMany l).1.getKey? k' = some k := by + simp_to_model using getKey?_insertList_of_mem + +theorem getKey_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k : α} + (h₁ : (l.map Sigma.fst).contains k = false) + {h'} : + (m.insertMany l).1.getKey k h' = + m.getKey k (contains_of_contains_insertMany_list _ h h' h₁) := by + simp_to_model using getKey_insertList_of_contains_eq_false + +theorem getKey_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) + {h'} : + (m.insertMany l).1.getKey k' h' = k := by + simp_to_model using getKey_insertList_of_mem + +theorem getKey!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] [Inhabited α] + (h : m.1.WF) {l : List ((a : α) × β a)} {k : α} + (h' : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).1.getKey! k = m.getKey! k := by + simp_to_model using getKey!_insertList_of_contains_eq_false + +theorem getKey!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] (h : m.1.WF) + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (m.insertMany l).1.getKey! k' = k := by + simp_to_model using getKey!_insertList_of_mem + +theorem getKeyD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ((a : α) × β a)} {k fallback : α} + (h' : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).1.getKeyD k fallback = m.getKeyD k fallback := by + simp_to_model using getKeyD_insertList_of_contains_eq_false + +theorem getKeyD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ((a : α) × β a)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (m.insertMany l).1.getKeyD k' fallback = k := by + simp_to_model using getKeyD_insertList_of_mem + +theorem size_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ((a : α) × β a)} (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (∀ (a : α), m.contains a → (l.map Sigma.fst).contains a = false) → + (m.insertMany l).1.1.size = m.1.size + l.length := by + simp_to_model using length_insertList + +theorem size_le_size_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ((a : α) × β a)} : + m.1.size ≤ (m.insertMany l).1.1.size := by + simp_to_model using length_le_length_insertList + +theorem size_insertMany_list_le [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ((a : α) × β a)} : + (m.insertMany l).1.1.size ≤ m.1.size + l.length := by + simp_to_model using length_insertList_le + +@[simp] +theorem isEmpty_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ((a : α) × β a)} : + (m.insertMany l).1.1.isEmpty = (m.1.isEmpty && l.isEmpty) := by + simp_to_model using isEmpty_insertList + +namespace Const + +variable {β : Type v} (m : Raw₀ α (fun _ => β)) + +@[simp] +theorem insertMany_nil : + insertMany m [] = m := by + simp [insertMany, Id.run] + +@[simp] +theorem insertMany_list_singleton {k : α} {v : β} : + insertMany m [⟨k, v⟩] = m.insert k v := by + simp [insertMany, Id.run] + +theorem insertMany_cons {l : List (α × β)} {k : α} {v : β} : + (insertMany m (⟨k, v⟩ :: l)).1 = (insertMany (m.insert k v) l).1 := by + simp only [insertMany_eq_insertListₘ] + cases l with + | nil => simp [insertListₘ] + | cons hd tl => simp [insertListₘ] + +@[simp] +theorem contains_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} {k : α} : + (Const.insertMany m l).1.contains k = (m.contains k || (l.map Prod.fst).contains k) := by + simp_to_model using containsKey_insertListConst + +theorem contains_of_contains_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List ( α × β )} {k : α} : + (insertMany m l).1.contains k → (l.map Prod.fst).contains k = false → m.contains k := by + simp_to_model using containsKey_of_containsKey_insertListConst + +theorem getKey?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} {k : α} + (h' : (l.map Prod.fst).contains k = false) : + (insertMany m l).1.getKey? k = m.getKey? k := by + simp_to_model using getKey?_insertListConst_of_contains_eq_false + +theorem getKey?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).1.getKey? k' = some k := by + simp_to_model using getKey?_insertListConst_of_mem + +theorem getKey_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} {k : α} + (h₁ : (l.map Prod.fst).contains k = false) + {h'} : + (insertMany m l).1.getKey k h' = + m.getKey k (contains_of_contains_insertMany_list _ h h' h₁) := by + simp_to_model using getKey_insertListConst_of_contains_eq_false + +theorem getKey_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) + {h'} : + (insertMany m l).1.getKey k' h' = k := by + simp_to_model using getKey_insertListConst_of_mem + +theorem getKey!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] [Inhabited α] + (h : m.1.WF) {l : List (α × β)} {k : α} + (h' : (l.map Prod.fst).contains k = false) : + (insertMany m l).1.getKey! k = m.getKey! k := by + simp_to_model using getKey!_insertListConst_of_contains_eq_false + +theorem getKey!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] (h : m.1.WF) + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).1.getKey! k' = k := by + simp_to_model using getKey!_insertListConst_of_mem + +theorem getKeyD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} {k fallback : α} + (h' : (l.map Prod.fst).contains k = false) : + (insertMany m l).1.getKeyD k fallback = m.getKeyD k fallback := by + simp_to_model using getKeyD_insertListConst_of_contains_eq_false + +theorem getKeyD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).1.getKeyD k' fallback = k := by + simp_to_model using getKeyD_insertListConst_of_mem + +theorem size_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (∀ (a : α), m.contains a → (l.map Prod.fst).contains a = false) → + (insertMany m l).1.1.size = m.1.size + l.length := by + simp_to_model using length_insertListConst + +theorem size_le_size_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} : + m.1.size ≤ (insertMany m l).1.1.size := by + simp_to_model using length_le_length_insertListConst + +theorem size_insertMany_list_le [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} : + (insertMany m l).1.1.size ≤ m.1.size + l.length := by + simp_to_model using length_insertListConst_le + +@[simp] +theorem isEmpty_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} : + (insertMany m l).1.1.isEmpty = (m.1.isEmpty && l.isEmpty) := by + simp_to_model using isEmpty_insertListConst + +theorem get?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} {k : α} + (h' : (l.map Prod.fst).contains k = false) : + get? (insertMany m l).1 k = get? m k := by + simp_to_model using getValue?_insertListConst_of_contains_eq_false + +theorem get?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + get? (insertMany m l).1 k' = v := by + simp_to_model using getValue?_insertListConst_of_mem + +theorem get_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} {k : α} + (h₁ : (l.map Prod.fst).contains k = false) + {h'} : + get (insertMany m l).1 k h' = get m k (contains_of_contains_insertMany_list _ h h' h₁) := by + simp_to_model using getValue_insertListConst_of_contains_eq_false + +theorem get_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) {h'} : + get (insertMany m l).1 k' h' = v := by + simp_to_model using getValue_insertListConst_of_mem + +theorem get!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited β] (h : m.1.WF) {l : List (α × β)} {k : α} + (h' : (l.map Prod.fst).contains k = false) : + get! (insertMany m l).1 k = get! m k := by + simp_to_model using getValue!_insertListConst_of_contains_eq_false + +theorem get!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited β] (h : m.1.WF) + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + get! (insertMany m l).1 k' = v := by + simp_to_model using getValue!_insertListConst_of_mem + +theorem getD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} {k : α} {fallback : β} + (h' : (l.map Prod.fst).contains k = false) : + getD (insertMany m l).1 k fallback = getD m k fallback := by + simp_to_model using getValueD_insertListConst_of_contains_eq_false + +theorem getD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v fallback : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + getD (insertMany m l).1 k' fallback = v := by + simp_to_model using getValueD_insertListConst_of_mem + +variable (m : Raw₀ α (fun _ => Unit)) + +@[simp] +theorem insertManyIfNewUnit_nil : + insertManyIfNewUnit m [] = m := by + simp [insertManyIfNewUnit, Id.run] + +@[simp] +theorem insertManyIfNewUnit_list_singleton {k : α} : + insertManyIfNewUnit m [k] = m.insertIfNew k () := by + simp [insertManyIfNewUnit, Id.run] + +theorem insertManyIfNewUnit_cons {l : List α} {k : α} : + (insertManyIfNewUnit m (k :: l)).1 = (insertManyIfNewUnit (m.insertIfNew k ()) l).1 := by + simp only [insertManyIfNewUnit_eq_insertListIfNewUnitₘ] + cases l with + | nil => simp [insertListIfNewUnitₘ] + | cons hd tl => simp [insertListIfNewUnitₘ] + +@[simp] +theorem contains_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List α} {k : α} : + (insertManyIfNewUnit m l).1.contains k = (m.contains k || l.contains k) := by + simp_to_model using containsKey_insertListIfNewUnit + +theorem contains_of_contains_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List α} {k : α} (h₂ : l.contains k = false) : + (insertManyIfNewUnit m l).1.contains k → m.contains k := by + simp_to_model using containsKey_of_containsKey_insertListIfNewUnit + +theorem getKey?_insertManyIfNewUnit_list_of_contains_eq_false_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] + (h : m.1.WF) {l : List α} {k : α} : + m.contains k = false → l.contains k = false → getKey? (insertManyIfNewUnit m l).1 k = none := by + simp_to_model using getKey?_insertListIfNewUnit_of_contains_eq_false_of_contains_eq_false + +theorem getKey?_insertManyIfNewUnit_list_of_contains_eq_false_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.1.WF) {l : List α} {k k' : α} (k_beq : k == k') : + m.contains k = false → l.Pairwise (fun a b => (a == b) = false) → k ∈ l → + getKey? (insertManyIfNewUnit m l).1 k' = some k := by + simp_to_model using getKey?_insertListIfNewUnit_of_contains_eq_false_of_mem + +theorem getKey?_insertManyIfNewUnit_list_of_contains [EquivBEq α] [LawfulHashable α] + (h : m.1.WF) {l : List α} {k : α} : + m.contains k → getKey? (insertManyIfNewUnit m l).1 k = getKey? m k := by + simp_to_model using getKey?_insertListIfNewUnit_of_contains + +theorem getKey_insertManyIfNewUnit_list_of_contains [EquivBEq α] [LawfulHashable α] + (h : m.1.WF) {l : List α} {k : α} {h'} (contains : m.contains k): + getKey (insertManyIfNewUnit m l).1 k h' = getKey m k contains := by + simp_to_model using getKey_insertListIfNewUnit_of_contains + +theorem getKey_insertManyIfNewUnit_list_of_contains_eq_false_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.1.WF) {l : List α} + {k k' : α} (k_beq : k == k') {h'} : + m.contains k = false → l.Pairwise (fun a b => (a == b) = false) → k ∈ l → + getKey (insertManyIfNewUnit m l).1 k' h' = k := by + simp_to_model using getKey_insertListIfNewUnit_of_contains_eq_false_of_mem + +theorem getKey_insertManyIfNewUnit_list_mem_of_contains [EquivBEq α] [LawfulHashable α] + (h : m.1.WF) {l : List α} {k : α} (contains : m.contains k) {h'} : + getKey (insertManyIfNewUnit m l).1 k h' = getKey m k contains := by + simp_to_model using getKey_insertListIfNewUnit_of_contains + +theorem getKey!_insertManyIfNewUnit_list_of_contains_eq_false_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] [Inhabited α] (h : m.1.WF) {l : List α} {k : α} : + m.contains k = false → l.contains k = false → + getKey! (insertManyIfNewUnit m l).1 k = default := by + simp_to_model using getKey!_insertListIfNewUnit_of_contains_eq_false_of_contains_eq_false + +theorem getKey!_insertManyIfNewUnit_list_of_contains_eq_false_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] (h : m.1.WF) {l : List α} {k k' : α} (k_beq : k == k') : + contains m k = false → l.Pairwise (fun a b => (a == b) = false) → k ∈ l → + getKey! (insertManyIfNewUnit m l).1 k' = k := by + simp_to_model using getKey!_insertListIfNewUnit_of_contains_eq_false_of_mem + +theorem getKey!_insertManyIfNewUnit_list_of_contains [EquivBEq α] [LawfulHashable α] + [Inhabited α] (h : m.1.WF) {l : List α} {k : α} : + m.contains k → getKey! (insertManyIfNewUnit m l).1 k = getKey! m k := by + simp_to_model using getKey!_insertListIfNewUnit_of_contains + +theorem getKeyD_insertManyIfNewUnit_list_of_contains_eq_false_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] (h : m.1.WF) {l : List α} {k fallback : α} : + m.contains k = false → l.contains k = false → getKeyD (insertManyIfNewUnit m l).1 k fallback = fallback := by + simp_to_model using getKeyD_insertListIfNewUnit_of_contains_eq_false_of_contains_eq_false + +theorem getKeyD_insertManyIfNewUnit_list_of_contains_eq_false_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.1.WF) {l : List α} {k k' fallback : α} (k_beq : k == k') : + m.contains k = false → l.Pairwise (fun a b => (a == b) = false) → k ∈ l → + getKeyD (insertManyIfNewUnit m l).1 k' fallback = k := by + simp_to_model using getKeyD_insertListIfNewUnit_of_contains_eq_false_of_mem + +theorem getKeyD_insertManyIfNewUnit_list_of_contains [EquivBEq α] [LawfulHashable α] + (h : m.1.WF) {l : List α} {k fallback : α} : + m.contains k → getKeyD (insertManyIfNewUnit m l).1 k fallback = getKeyD m k fallback := by + simp_to_model using getKeyD_insertListIfNewUnit_of_contains + +theorem size_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (∀ (a : α), m.contains a → l.contains a = false) → + (insertManyIfNewUnit m l).1.1.size = m.1.size + l.length := by + simp_to_model using length_insertListIfNewUnit + +theorem size_le_size_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List α} : + m.1.size ≤ (insertManyIfNewUnit m l).1.1.size := by + simp_to_model using length_le_length_insertListIfNewUnit + +theorem size_insertManyIfNewUnit_list_le [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List α} : + (insertManyIfNewUnit m l).1.1.size ≤ m.1.size + l.length := by + simp_to_model using length_insertListIfNewUnit_le + +@[simp] +theorem isEmpty_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List α} : + (insertManyIfNewUnit m l).1.1.isEmpty = (m.1.isEmpty && l.isEmpty) := by + simp_to_model using isEmpty_insertListIfNewUnit + +theorem get?_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.1.WF) + {l : List α} {k : α} : + get? (insertManyIfNewUnit m l).1 k = + if m.contains k ∨ l.contains k then some () else none := by + simp_to_model using getValue?_insertListIfNewUnit + +theorem get_insertManyIfNewUnit_list + {l : List α} {k : α} {h} : + get (insertManyIfNewUnit m l).1 k h = () := by + simp + +theorem get!_insertManyIfNewUnit_list + {l : List α} {k : α} : + get! (insertManyIfNewUnit m l).1 k = () := by + simp + +theorem getD_insertManyIfNewUnit_list + {l : List α} {k : α} {fallback : Unit} : + getD (insertManyIfNewUnit m l).1 k fallback = () := by + simp + +end Const + +end Raw₀ + +namespace Raw₀ + +variable [BEq α] [Hashable α] + +@[simp] +theorem insertMany_empty_list_nil : + (insertMany empty ([] : List ((a : α) × (β a)))).1 = empty := by + simp + +@[simp] +theorem insertMany_empty_list_singleton {k : α} {v : β k} : + (insertMany empty [⟨k, v⟩]).1 = empty.insert k v := by + simp + +theorem insertMany_empty_list_cons {k : α} {v : β k} + {tl : List ((a : α) × (β a))} : + (insertMany empty (⟨k, v⟩ :: tl)).1 = ((empty.insert k v).insertMany tl).1 := by + rw [insertMany_cons] + +theorem contains_insertMany_empty_list [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} : + (insertMany empty l).1.contains k = (l.map Sigma.fst).contains k := by + simp [contains_insertMany_list _ Raw.WF.empty₀] + +theorem get?_insertMany_empty_list_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} + (h : (l.map Sigma.fst).contains k = false) : + (insertMany empty l).1.get? k = none := by + simp [get?_insertMany_list_of_contains_eq_false _ Raw.WF.empty₀ h] + +theorem get?_insertMany_empty_list_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (insertMany empty l).1.get? k' = some (cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v) := by + rw [get?_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem get_insertMany_empty_list_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) + {h} : + (insertMany empty l).1.get k' h = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := by + rw [get_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem get!_insertMany_empty_list_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} [Inhabited (β k)] + (h : (l.map Sigma.fst).contains k = false) : + (insertMany empty l).1.get! k = default := by + simp only [get!_insertMany_list_of_contains_eq_false _ Raw.WF.empty₀ h] + apply get!_empty + +theorem get!_insertMany_empty_list_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} [Inhabited (β k')] + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (insertMany empty l).1.get! k' = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := by + rw [get!_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem getD_insertMany_empty_list_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} {fallback : β k} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (insertMany empty l).1.getD k fallback = fallback := by + rw [getD_insertMany_list_of_contains_eq_false _ Raw.WF.empty₀ contains_eq_false] + apply getD_empty + +theorem getD_insertMany_empty_list_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} {fallback : β k'} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (insertMany empty l).1.getD k' fallback = + cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := by + rw [getD_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem getKey?_insertMany_empty_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} + (h : (l.map Sigma.fst).contains k = false) : + (insertMany empty l).1.getKey? k = none := by + rw [getKey?_insertMany_list_of_contains_eq_false _ Raw.WF.empty₀ h] + apply getKey?_empty + +theorem getKey?_insertMany_empty_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (insertMany empty l).1.getKey? k' = some k := by + rw [getKey?_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem getKey_insertMany_empty_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) + {h'} : + (insertMany empty l).1.getKey k' h' = k := by + rw [getKey_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem getKey!_insertMany_empty_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List ((a : α) × β a)} {k : α} + (h : (l.map Sigma.fst).contains k = false) : + (insertMany empty l).1.getKey! k = default := by + rw [getKey!_insertMany_list_of_contains_eq_false _ Raw.WF.empty₀ h] + apply getKey!_empty + +theorem getKey!_insertMany_empty_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (insertMany empty l).1.getKey! k' = k := by + rw [getKey!_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem getKeyD_insertMany_empty_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k fallback : α} + (h : (l.map Sigma.fst).contains k = false) : + (insertMany empty l).1.getKeyD k fallback = fallback := by + rw [getKeyD_insertMany_list_of_contains_eq_false _ Raw.WF.empty₀ h] + apply getKeyD_empty + +theorem getKeyD_insertMany_empty_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (insertMany empty l).1.getKeyD k' fallback = k := by + rw [getKeyD_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem size_insertMany_empty_list [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (insertMany empty l).1.1.size = l.length := by + rw [size_insertMany_list _ Raw.WF.empty₀ distinct] + · simp only [size_empty, Nat.zero_add] + · simp only [contains_empty, Bool.false_eq_true, false_implies, implies_true] + +theorem size_insertMany_empty_list_le [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} : + (insertMany empty l).1.1.size ≤ l.length := by + rw [← Nat.zero_add l.length] + apply (size_insertMany_list_le _ Raw.WF.empty₀) + +theorem isEmpty_insertMany_empty_list [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} : + (insertMany empty l).1.1.isEmpty = l.isEmpty := by + simp [isEmpty_insertMany_list _ Raw.WF.empty₀] + +namespace Const +variable {β : Type v} + +@[simp] +theorem insertMany_empty_list_nil : + (insertMany empty ([] : List (α × β))).1 = empty := by + simp only [insertMany_nil] + +@[simp] +theorem insertMany_empty_list_singleton {k : α} {v : β} : + (insertMany empty [⟨k, v⟩]).1 = empty.insert k v := by + simp only [insertMany_list_singleton] + +theorem insertMany_empty_list_cons {k : α} {v : β} + {tl : List (α × β)} : + (insertMany empty (⟨k, v⟩ :: tl)) = (insertMany (empty.insert k v) tl).1 := by + rw [insertMany_cons] + +theorem contains_insertMany_empty_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + (insertMany (empty : Raw₀ α (fun _ => β)) l).1.contains k = (l.map Prod.fst).contains k := by + simp [contains_insertMany_list _ Raw.WF.empty₀] + +theorem get?_insertMany_empty_list_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} + (h : (l.map Prod.fst).contains k = false) : + get? (insertMany (empty : Raw₀ α (fun _ => β)) l).1 k = none := by + rw [get?_insertMany_list_of_contains_eq_false _ Raw.WF.empty₀ h] + apply get?_empty + +theorem get?_insertMany_empty_list_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + get? (insertMany (empty : Raw₀ α (fun _ => β)) l) k' = some v := by + rw [get?_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem get_insertMany_empty_list_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) + {h} : + get (insertMany (empty : Raw₀ α (fun _ => β)) l) k' h = v := by + rw [get_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem get!_insertMany_empty_list_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} [Inhabited β] + (h : (l.map Prod.fst).contains k = false) : + get! (insertMany (empty : Raw₀ α (fun _ => β)) l) k = (default : β) := by + rw [get!_insertMany_list_of_contains_eq_false _ Raw.WF.empty₀ h] + apply get!_empty + +theorem get!_insertMany_empty_list_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} [Inhabited β] + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + get! (insertMany (empty : Raw₀ α (fun _ => β)) l) k' = v := by + rw [get!_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem getD_insertMany_empty_list_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} {fallback : β} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + getD (insertMany (empty : Raw₀ α (fun _ => β)) l) k fallback = fallback := by + rw [getD_insertMany_list_of_contains_eq_false _ Raw.WF.empty₀ contains_eq_false] + apply getD_empty + +theorem getD_insertMany_empty_list_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} {fallback : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + getD (insertMany (empty : Raw₀ α (fun _ => β)) l) k' fallback = v := by + rw [getD_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem getKey?_insertMany_empty_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (h : (l.map Prod.fst).contains k = false) : + (insertMany (empty : Raw₀ α (fun _ => β)) l).1.getKey? k = none := by + rw [getKey?_insertMany_list_of_contains_eq_false _ Raw.WF.empty₀ h] + apply getKey?_empty + +theorem getKey?_insertMany_empty_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany (empty : Raw₀ α (fun _ => β)) l).1.getKey? k' = some k := by + rw [getKey?_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem getKey_insertMany_empty_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) + {h'} : + (insertMany (empty : Raw₀ α (fun _ => β)) l).1.getKey k' h' = k := by + rw [getKey_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem getKey!_insertMany_empty_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List (α × β)} {k : α} + (h : (l.map Prod.fst).contains k = false) : + (insertMany (empty : Raw₀ α (fun _ => β)) l).1.getKey! k = default := by + rw [getKey!_insertMany_list_of_contains_eq_false _ Raw.WF.empty₀ h] + apply getKey!_empty + +theorem getKey!_insertMany_empty_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany (empty : Raw₀ α (fun _ => β)) l).1.getKey! k' = k := by + rw [getKey!_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem getKeyD_insertMany_empty_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k fallback : α} + (h : (l.map Prod.fst).contains k = false) : + (insertMany (empty : Raw₀ α (fun _ => β)) l).1.getKeyD k fallback = fallback := by + rw [getKeyD_insertMany_list_of_contains_eq_false _ Raw.WF.empty₀ h] + apply getKeyD_empty + +theorem getKeyD_insertMany_empty_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany (empty : Raw₀ α (fun _ => β)) l).1.getKeyD k' fallback = k := by + rw [getKeyD_insertMany_list_of_mem _ Raw.WF.empty₀ k_beq distinct mem] + +theorem size_insertMany_empty_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (insertMany (empty : Raw₀ α (fun _ => β)) l).1.1.size = l.length := by + rw [size_insertMany_list _ Raw.WF.empty₀ distinct] + · simp only [size_empty, Nat.zero_add] + · simp only [contains_empty, Bool.false_eq_true, false_implies, implies_true] + +theorem size_insertMany_empty_list_le [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (insertMany (empty : Raw₀ α (fun _ => β)) l).1.1.size ≤ l.length := by + rw [← Nat.zero_add l.length] + apply (size_insertMany_list_le _ Raw.WF.empty₀) + +theorem isEmpty_insertMany_empty_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (insertMany (empty : Raw₀ α (fun _ => β)) l).1.1.isEmpty = l.isEmpty := by + simp [isEmpty_insertMany_list _ Raw.WF.empty₀] + +@[simp] +theorem insertManyIfNewUnit_empty_list_nil : + insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) ([] : List α) = + (empty : Raw₀ α (fun _ => Unit)) := by + simp + +@[simp] +theorem insertManyIfNewUnit_empty_list_singleton {k : α} : + (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) [k]).1 = empty.insertIfNew k () := by + simp + +theorem insertManyIfNewUnit_empty_list_cons {hd : α} {tl : List α} : + insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) (hd :: tl) = + (insertManyIfNewUnit (empty.insertIfNew hd ()) tl).1 := by + rw [insertManyIfNewUnit_cons] + +theorem contains_insertManyIfNewUnit_empty_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l).1.contains k = l.contains k := by + simp [contains_insertManyIfNewUnit_list _ Raw.WF.empty₀] + +theorem getKey?_insertManyIfNewUnit_empty_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (h' : l.contains k = false) : + getKey? (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l).1 k = none := by + exact getKey?_insertManyIfNewUnit_list_of_contains_eq_false_of_contains_eq_false _ Raw.WF.empty₀ + contains_empty h' + +theorem getKey?_insertManyIfNewUnit_empty_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getKey? (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l).1 k' = some k := by + exact getKey?_insertManyIfNewUnit_list_of_contains_eq_false_of_mem _ Raw.WF.empty₀ k_beq + contains_empty distinct mem + +theorem getKey_insertManyIfNewUnit_empty_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) {h'} : + getKey (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l).1 k' h' = k := by + exact getKey_insertManyIfNewUnit_list_of_contains_eq_false_of_mem _ Raw.WF.empty₀ k_beq + contains_empty distinct mem + +theorem getKey!_insertManyIfNewUnit_empty_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k : α} + (h' : l.contains k = false) : + getKey! (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l).1 k = default := by + exact getKey!_insertManyIfNewUnit_list_of_contains_eq_false_of_contains_eq_false _ Raw.WF.empty₀ + contains_empty h' + +theorem getKey!_insertManyIfNewUnit_empty_list_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + getKey! (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l).1 k' = k := by + exact getKey!_insertManyIfNewUnit_list_of_contains_eq_false_of_mem _ Raw.WF.empty₀ k_beq + contains_empty distinct mem + +theorem getKeyD_insertManyIfNewUnit_empty_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k fallback : α} + (h' : l.contains k = false) : + getKeyD (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l).1 k fallback = fallback := by + exact getKeyD_insertManyIfNewUnit_list_of_contains_eq_false_of_contains_eq_false + _ Raw.WF.empty₀ contains_empty h' + +theorem getKeyD_insertManyIfNewUnit_empty_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + getKeyD (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l).1 k' fallback = k := by + exact getKeyD_insertManyIfNewUnit_list_of_contains_eq_false_of_mem _ Raw.WF.empty₀ k_beq + contains_empty distinct mem + +theorem size_insertManyIfNewUnit_empty_list [EquivBEq α] [LawfulHashable α] + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l).1.1.size = l.length := by + simp [size_insertManyIfNewUnit_list _ Raw.WF.empty₀ distinct] + +theorem size_insertManyIfNewUnit_empty_list_le [EquivBEq α] [LawfulHashable α] + {l : List α} : + (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l).1.1.size ≤ l.length := by + apply Nat.le_trans (size_insertManyIfNewUnit_list_le _ Raw.WF.empty₀) + simp + +theorem isEmpty_insertManyIfNewUnit_empty_list [EquivBEq α] [LawfulHashable α] + {l : List α} : + (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l).1.1.isEmpty = l.isEmpty := by + rw [isEmpty_insertManyIfNewUnit_list _ Raw.WF.empty₀] + simp + +theorem get?_insertManyIfNewUnit_empty_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + get? (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l) k = + if l.contains k then some () else none := by + rw [get?_insertManyIfNewUnit_list _ Raw.WF.empty₀] + simp + +theorem get_insertManyIfNewUnit_empty_list + {l : List α} {k : α} {h} : + get (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l) k h = () := by + simp + +theorem get!_insertManyIfNewUnit_empty_list + {l : List α} {k : α} : + get! (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l) k = () := by + simp + +theorem getD_insertManyIfNewUnit_empty_list + {l : List α} {k : α} {fallback : Unit} : + getD (insertManyIfNewUnit (empty : Raw₀ α (fun _ => Unit)) l) k fallback = () := by + simp + +end Const + end Raw₀ end Std.DHashMap.Internal diff --git a/src/Std/Data/DHashMap/Internal/WF.lean b/src/Std/Data/DHashMap/Internal/WF.lean index 87e7e14870db..d441e5bf36ee 100644 --- a/src/Std/Data/DHashMap/Internal/WF.lean +++ b/src/Std/Data/DHashMap/Internal/WF.lean @@ -789,7 +789,7 @@ theorem Const.toListModel_getThenInsertIfNew? {β : Type v} [BEq α] [Hashable exact toListModel_insertIfNewₘ h theorem Const.wfImp_getThenInsertIfNew? {β : Type v} [BEq α] [Hashable α] [EquivBEq α] - [LawfulHashable α] {m : Raw₀ α (fun _ => β)} {a : α} {b : β} (h : Raw.WFImp m.1): + [LawfulHashable α] {m : Raw₀ α (fun _ => β)} {a : α} {b : β} (h : Raw.WFImp m.1) : Raw.WFImp (Const.getThenInsertIfNew? m a b).2.1 := by rw [getThenInsertIfNew?_eq_insertIfNewₘ] exact wfImp_insertIfNewₘ h @@ -955,6 +955,20 @@ theorem wfImp_filter [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] {m rw [filter_eq_filterₘ] exact wfImp_filterₘ h +/-! # `insertListₘ` -/ + +theorem toListModel_insertListₘ [BEq α] [Hashable α] [EquivBEq α][LawfulHashable α] + {m : Raw₀ α β} {l : List ((a : α) × β a)} (h : Raw.WFImp m.1) : + Perm (toListModel (insertListₘ m l).1.buckets) + (List.insertList (toListModel m.1.buckets) l) := by + induction l generalizing m with + | nil => + simp [insertListₘ, List.insertList] + | cons hd tl ih => + simp only [insertListₘ, List.insertList] + apply Perm.trans (ih (wfImp_insert h)) + apply List.insertList_perm_of_perm_first (toListModel_insert h) (wfImp_insert h).distinct + end Raw₀ namespace Raw @@ -981,16 +995,72 @@ end Raw namespace Raw₀ +/-! # `insertMany` -/ + theorem wfImp_insertMany [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] {ρ : Type w} [ForIn Id ρ ((a : α) × β a)] {m : Raw₀ α β} {l : ρ} (h : Raw.WFImp m.1) : Raw.WFImp (m.insertMany l).1.1 := Raw.WF.out ((m.insertMany l).2 _ Raw.WF.insert₀ (.wf m.2 h)) +theorem toListModel_insertMany_list [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] + {m : Raw₀ α β} {l : List ((a : α) × (β a))} (h : Raw.WFImp m.1) : + Perm (toListModel (insertMany m l).1.1.buckets) + (List.insertList (toListModel m.1.buckets) l) := by + rw [insertMany_eq_insertListₘ] + apply toListModel_insertListₘ + exact h + +/-! # `Const.insertListₘ` -/ + +theorem Const.toListModel_insertListₘ {β : Type v} [BEq α] [Hashable α] [EquivBEq α] + [LawfulHashable α] {m : Raw₀ α (fun _ => β)} {l : List (α × β)} (h : Raw.WFImp m.1) : + Perm (toListModel (Const.insertListₘ m l).1.buckets) + (insertListConst (toListModel m.1.buckets) l) := by + induction l generalizing m with + | nil => simp [Const.insertListₘ, insertListConst, insertList] + | cons hd tl ih => + simp only [Const.insertListₘ, insertListConst] + apply Perm.trans (ih (wfImp_insert h)) + unfold insertListConst + apply List.insertList_perm_of_perm_first (toListModel_insert h) (wfImp_insert h).distinct + +/-! # `Const.insertMany` -/ + +theorem Const.toListModel_insertMany_list {β : Type v} [BEq α] [Hashable α] [EquivBEq α] + [LawfulHashable α] {m : Raw₀ α (fun _ => β)} {l : List (α × β)} (h : Raw.WFImp m.1) : + Perm (toListModel (Const.insertMany m l).1.1.buckets) + (insertListConst (toListModel m.1.buckets) l) := by + rw [Const.insertMany_eq_insertListₘ] + apply toListModel_insertListₘ h + theorem Const.wfImp_insertMany {β : Type v} [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] {ρ : Type w} [ForIn Id ρ (α × β)] {m : Raw₀ α (fun _ => β)} {l : ρ} (h : Raw.WFImp m.1) : Raw.WFImp (Const.insertMany m l).1.1 := Raw.WF.out ((Const.insertMany m l).2 _ Raw.WF.insert₀ (.wf m.2 h)) +/-! # `Const.insertListIfNewUnitₘ` -/ + +theorem Const.toListModel_insertListIfNewUnitₘ [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] + {m : Raw₀ α (fun _ => Unit)} {l : List α} (h : Raw.WFImp m.1) : + Perm (toListModel (Const.insertListIfNewUnitₘ m l).1.buckets) + (List.insertListIfNewUnit (toListModel m.1.buckets) l) := by + induction l generalizing m with + | nil => simp [insertListIfNewUnitₘ, List.insertListIfNewUnit] + | cons hd tl ih => + simp only [insertListIfNewUnitₘ, insertListIfNewUnit] + apply Perm.trans (ih (wfImp_insertIfNew h)) + apply List.insertListIfNewUnit_perm_of_perm_first (toListModel_insertIfNew h) + apply (wfImp_insertIfNew h).distinct + +/-! # `Const.insertManyIfNewUnit` -/ + +theorem Const.toListModel_insertManyIfNewUnit_list [BEq α] [Hashable α] [EquivBEq α] + [LawfulHashable α] {m : Raw₀ α (fun _ => Unit)} {l : List α} (h : Raw.WFImp m.1) : + Perm (toListModel (Const.insertManyIfNewUnit m l).1.1.buckets) + (List.insertListIfNewUnit (toListModel m.1.buckets) l) := by + rw [Const.insertManyIfNewUnit_eq_insertListIfNewUnitₘ] + apply toListModel_insertListIfNewUnitₘ h + theorem Const.wfImp_insertManyIfNewUnit [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] {ρ : Type w} [ForIn Id ρ α] {m : Raw₀ α (fun _ => Unit)} {l : ρ} (h : Raw.WFImp m.1) : Raw.WFImp (Const.insertManyIfNewUnit m l).1.1 := diff --git a/src/Std/Data/DHashMap/Lemmas.lean b/src/Std/Data/DHashMap/Lemmas.lean index bb61c54e1d2f..7d2eebadcef7 100644 --- a/src/Std/Data/DHashMap/Lemmas.lean +++ b/src/Std/Data/DHashMap/Lemmas.lean @@ -913,7 +913,6 @@ theorem getKeyD_insertIfNew [EquivBEq α] [LawfulHashable α] {k a fallback : α simp [mem_iff_contains, contains_insertIfNew] exact Raw₀.getKeyD_insertIfNew ⟨m.1, _⟩ m.2 - @[simp] theorem getThenInsertIfNew?_fst [LawfulBEq α] {k : α} {v : β k} : (m.getThenInsertIfNew? k v).1 = m.get? k := @@ -964,4 +963,907 @@ theorem distinct_keys [EquivBEq α] [LawfulHashable α] : m.keys.Pairwise (fun a b => (a == b) = false) := Raw₀.distinct_keys ⟨m.1, m.2.size_buckets_pos⟩ m.2 +@[simp] +theorem insertMany_nil : + m.insertMany [] = m := + Subtype.eq (congrArg Subtype.val (Raw₀.insertMany_nil ⟨m.1, m.2.size_buckets_pos⟩) :) + +@[simp] +theorem insertMany_list_singleton {k : α} {v : β k} : + m.insertMany [⟨k, v⟩] = m.insert k v := + Subtype.eq (congrArg Subtype.val (Raw₀.insertMany_list_singleton ⟨m.1, m.2.size_buckets_pos⟩) :) + +theorem insertMany_cons {l : List ((a : α) × β a)} {k : α} {v : β k} : + m.insertMany (⟨k, v⟩ :: l) = (m.insert k v).insertMany l := + Subtype.eq (congrArg Subtype.val (Raw₀.insertMany_cons ⟨m.1, m.2.size_buckets_pos⟩) :) + +@[simp] +theorem contains_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} : + (m.insertMany l).contains k = (m.contains k || (l.map Sigma.fst).contains k) := + Raw₀.contains_insertMany_list ⟨m.1, _⟩ m.2 + +@[simp] +theorem mem_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} : + k ∈ m.insertMany l ↔ k ∈ m ∨ (l.map Sigma.fst).contains k := by + simp [mem_iff_contains] + +theorem mem_of_mem_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} (mem : k ∈ m.insertMany l) + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + k ∈ m := + Raw₀.contains_of_contains_insertMany_list ⟨m.1, _⟩ m.2 mem contains_eq_false + +theorem get?_insertMany_list_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).get? k = m.get? k := + Raw₀.get?_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem get?_insertMany_list_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (m.insertMany l).get? k' = some (cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v) := + Raw₀.get?_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem get_insertMany_list_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) + {h} : + (m.insertMany l).get k h = + m.get k (mem_of_mem_insertMany_list h contains_eq_false) := + Raw₀.get_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem get_insertMany_list_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) + {h} : + (m.insertMany l).get k' h = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := + Raw₀.get_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem get!_insertMany_list_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} [Inhabited (β k)] + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).get! k = m.get! k := + Raw₀.get!_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem get!_insertMany_list_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} [Inhabited (β k')] + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (m.insertMany l).get! k' = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := + Raw₀.get!_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem getD_insertMany_list_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} {fallback : β k} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).getD k fallback = m.getD k fallback := + Raw₀.getD_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem getD_insertMany_list_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} {fallback : β k'} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (m.insertMany l).getD k' fallback = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := + Raw₀.getD_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem getKey?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).getKey? k = m.getKey? k := + Raw₀.getKey?_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem getKey?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (m.insertMany l).getKey? k' = some k := + Raw₀.getKey?_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem getKey_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) + {h} : + (m.insertMany l).getKey k h = + m.getKey k (mem_of_mem_insertMany_list h contains_eq_false) := + Raw₀.getKey_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem getKey_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) + {h} : + (m.insertMany l).getKey k' h = k := + Raw₀.getKey_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem getKey!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).getKey! k = m.getKey! k := + Raw₀.getKey!_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem getKey!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (m.insertMany l).getKey! k' = k := + Raw₀.getKey!_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem getKeyD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k fallback : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).getKeyD k fallback = m.getKeyD k fallback := + Raw₀.getKeyD_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem getKeyD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (m.insertMany l).getKeyD k' fallback = k := + Raw₀.getKeyD_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem size_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (∀ (a : α), a ∈ m → (l.map Sigma.fst).contains a = false) → + (m.insertMany l).size = m.size + l.length := + Raw₀.size_insertMany_list ⟨m.1, _⟩ m.2 distinct + +theorem size_le_size_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} : + m.size ≤ (m.insertMany l).size := + Raw₀.size_le_size_insertMany_list ⟨m.1, _⟩ m.2 + +theorem size_insertMany_list_le [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} : + (m.insertMany l).size ≤ m.size + l.length := + Raw₀.size_insertMany_list_le ⟨m.1, _⟩ m.2 + +@[simp] +theorem isEmpty_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} : + (m.insertMany l).isEmpty = (m.isEmpty && l.isEmpty) := + Raw₀.isEmpty_insertMany_list ⟨m.1, _⟩ m.2 + +namespace Const + +variable {β : Type v} {m : DHashMap α (fun _ => β)} + +@[simp] +theorem insertMany_nil : + insertMany m [] = m := + Subtype.eq (congrArg Subtype.val (Raw₀.Const.insertMany_nil ⟨m.1, m.2.size_buckets_pos⟩) :) + +@[simp] +theorem insertMany_list_singleton {k : α} {v : β} : + insertMany m [⟨k, v⟩] = m.insert k v := + Subtype.eq (congrArg Subtype.val + (Raw₀.Const.insertMany_list_singleton ⟨m.1, m.2.size_buckets_pos⟩) :) + +theorem insertMany_cons {l : List (α × β)} {k : α} {v : β} : + insertMany m (⟨k, v⟩ :: l) = insertMany (m.insert k v) l := + Subtype.eq (congrArg Subtype.val (Raw₀.Const.insertMany_cons ⟨m.1, m.2.size_buckets_pos⟩) :) + +@[simp] +theorem contains_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + (Const.insertMany m l).contains k = (m.contains k || (l.map Prod.fst).contains k) := + Raw₀.Const.contains_insertMany_list ⟨m.1, _⟩ m.2 + +@[simp] +theorem mem_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + k ∈ insertMany m l ↔ k ∈ m ∨ (l.map Prod.fst).contains k := by + simp [mem_iff_contains] + +theorem mem_of_mem_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} (mem : k ∈ insertMany m l) + (contains_eq_false : (l.map Prod.fst).contains k = false) : + k ∈ m := + Raw₀.Const.contains_of_contains_insertMany_list ⟨m.1, _⟩ m.2 mem contains_eq_false + +theorem getKey?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l).getKey? k = m.getKey? k := + Raw₀.Const.getKey?_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem getKey?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).getKey? k' = some k := + Raw₀.Const.getKey?_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem getKey_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) + {h} : + (insertMany m l).getKey k h = + m.getKey k (mem_of_mem_insertMany_list h contains_eq_false) := + Raw₀.Const.getKey_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem getKey_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) + {h} : + (insertMany m l).getKey k' h = k := + Raw₀.Const.getKey_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem getKey!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l).getKey! k = m.getKey! k := + Raw₀.Const.getKey!_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem getKey!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).getKey! k' = k := + Raw₀.Const.getKey!_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem getKeyD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k fallback : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l).getKeyD k fallback = m.getKeyD k fallback := + Raw₀.Const.getKeyD_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem getKeyD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).getKeyD k' fallback = k := + Raw₀.Const.getKeyD_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem size_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (∀ (a : α), a ∈ m → (l.map Prod.fst).contains a = false) → + (insertMany m l).size = m.size + l.length := + Raw₀.Const.size_insertMany_list ⟨m.1, _⟩ m.2 distinct + +theorem size_le_size_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + m.size ≤ (insertMany m l).size := + Raw₀.Const.size_le_size_insertMany_list ⟨m.1, _⟩ m.2 + +theorem size_insertMany_list_le [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (insertMany m l).size ≤ m.size + l.length := + Raw₀.Const.size_insertMany_list_le ⟨m.1, _⟩ m.2 + +@[simp] +theorem isEmpty_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (insertMany m l).isEmpty = (m.isEmpty && l.isEmpty) := + Raw₀.Const.isEmpty_insertMany_list ⟨m.1, _⟩ m.2 + +theorem get?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + get? (insertMany m l) k = get? m k := + Raw₀.Const.get?_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem get?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + get? (insertMany m l) k' = v := + Raw₀.Const.get?_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem get_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) + {h} : + get (insertMany m l) k h = get m k (mem_of_mem_insertMany_list h contains_eq_false) := + Raw₀.Const.get_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem get_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) {h} : + get (insertMany m l) k' h = v := + Raw₀.Const.get_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem get!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited β] {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + get! (insertMany m l) k = get! m k := + Raw₀.Const.get!_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem get!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited β] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + get! (insertMany m l) k' = v := + Raw₀.Const.get!_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +theorem getD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} {fallback : β} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + getD (insertMany m l) k fallback = getD m k fallback := + Raw₀.Const.getD_insertMany_list_of_contains_eq_false ⟨m.1, _⟩ m.2 contains_eq_false + +theorem getD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v fallback : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + getD (insertMany m l) k' fallback = v := + Raw₀.Const.getD_insertMany_list_of_mem ⟨m.1, _⟩ m.2 k_beq distinct mem + +variable {m : DHashMap α (fun _ => Unit)} + +@[simp] +theorem insertManyIfNewUnit_nil : + insertManyIfNewUnit m [] = m := + Subtype.eq (congrArg Subtype.val + (Raw₀.Const.insertManyIfNewUnit_nil ⟨m.1, m.2.size_buckets_pos⟩) :) + +@[simp] +theorem insertManyIfNewUnit_list_singleton {k : α} : + insertManyIfNewUnit m [k] = m.insertIfNew k () := + Subtype.eq (congrArg Subtype.val + (Raw₀.Const.insertManyIfNewUnit_list_singleton ⟨m.1, m.2.size_buckets_pos⟩) :) + +theorem insertManyIfNewUnit_cons {l : List α} {k : α} : + insertManyIfNewUnit m (k :: l) = insertManyIfNewUnit (m.insertIfNew k ()) l := + Subtype.eq (congrArg Subtype.val + (Raw₀.Const.insertManyIfNewUnit_cons ⟨m.1, m.2.size_buckets_pos⟩) :) + +@[simp] +theorem contains_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (insertManyIfNewUnit m l).contains k = (m.contains k || l.contains k) := + Raw₀.Const.contains_insertManyIfNewUnit_list ⟨m.1, _⟩ m.2 + +@[simp] +theorem mem_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + k ∈ insertManyIfNewUnit m l ↔ k ∈ m ∨ l.contains k := by + simp [mem_iff_contains] + +theorem mem_of_mem_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (contains_eq_false : l.contains k = false) : + k ∈ insertManyIfNewUnit m l → k ∈ m := + Raw₀.Const.contains_of_contains_insertManyIfNewUnit_list ⟨m.1, _⟩ m.2 contains_eq_false + +theorem getKey?_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] {l : List α} {k : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + getKey? (insertManyIfNewUnit m l) k = none := by + simp only [mem_iff_contains, Bool.not_eq_true] at not_mem + exact Raw₀.Const.getKey?_insertManyIfNewUnit_list_of_contains_eq_false_of_contains_eq_false + ⟨m.1, _⟩ m.2 not_mem contains_eq_false + +theorem getKey?_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getKey? (insertManyIfNewUnit m l) k' = some k := by + simp only [mem_iff_contains, Bool.not_eq_true] at not_mem + exact Raw₀.Const.getKey?_insertManyIfNewUnit_list_of_contains_eq_false_of_mem ⟨m.1, _⟩ + m.2 k_beq not_mem distinct mem + +theorem getKey?_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (h' : k ∈ m) : + getKey? (insertManyIfNewUnit m l) k = getKey? m k := + Raw₀.Const.getKey?_insertManyIfNewUnit_list_of_contains ⟨m.1, _⟩ m.2 h' + +theorem getKey_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} + {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) {h} : + getKey (insertManyIfNewUnit m l) k' h = k := by + simp only [mem_iff_contains, Bool.not_eq_true] at not_mem + exact Raw₀.Const.getKey_insertManyIfNewUnit_list_of_contains_eq_false_of_mem ⟨m.1, _⟩ m.2 k_beq + not_mem distinct mem + +theorem getKey_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (mem : k ∈ m) {h} : + getKey (insertManyIfNewUnit m l) k h = getKey m k mem := + Raw₀.Const.getKey_insertManyIfNewUnit_list_of_contains ⟨m.1, _⟩ m.2 _ + +theorem getKey!_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] [Inhabited α] {l : List α} {k : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + getKey! (insertManyIfNewUnit m l) k = default := by + simp only [mem_iff_contains, Bool.not_eq_true] at not_mem + exact Raw₀.Const.getKey!_insertManyIfNewUnit_list_of_contains_eq_false_of_contains_eq_false + ⟨m.1, _⟩ m.2 not_mem contains_eq_false + +theorem getKey!_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + getKey! (insertManyIfNewUnit m l) k' = k := by + simp only [mem_iff_contains, Bool.not_eq_true] at not_mem + exact Raw₀.Const.getKey!_insertManyIfNewUnit_list_of_contains_eq_false_of_mem ⟨m.1, _⟩ m.2 k_beq + not_mem distinct mem + +theorem getKey!_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k : α} (mem : k ∈ m) : + getKey! (insertManyIfNewUnit m l) k = getKey! m k := + Raw₀.Const.getKey!_insertManyIfNewUnit_list_of_contains ⟨m.1, _⟩ m.2 mem + +theorem getKeyD_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] {l : List α} {k fallback : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + getKeyD (insertManyIfNewUnit m l) k fallback = fallback := by + simp only [mem_iff_contains, Bool.not_eq_true] at not_mem + exact Raw₀.Const.getKeyD_insertManyIfNewUnit_list_of_contains_eq_false_of_contains_eq_false + ⟨m.1, _⟩ m.2 not_mem contains_eq_false + +theorem getKeyD_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' fallback : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getKeyD (insertManyIfNewUnit m l) k' fallback = k := by + simp only [mem_iff_contains, Bool.not_eq_true] at not_mem + exact Raw₀.Const.getKeyD_insertManyIfNewUnit_list_of_contains_eq_false_of_mem ⟨m.1, _⟩ m.2 k_beq + not_mem distinct mem + +theorem getKeyD_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k fallback : α} (mem : k ∈ m) : + getKeyD (insertManyIfNewUnit m l) k fallback = getKeyD m k fallback := + Raw₀.Const.getKeyD_insertManyIfNewUnit_list_of_contains ⟨m.1, _⟩ m.2 mem + +theorem size_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (∀ (a : α), a ∈ m → l.contains a = false) → + (insertManyIfNewUnit m l).size = m.size + l.length := + Raw₀.Const.size_insertManyIfNewUnit_list ⟨m.1, _⟩ m.2 distinct + +theorem size_le_size_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} : + m.size ≤ (insertManyIfNewUnit m l).size := + Raw₀.Const.size_le_size_insertManyIfNewUnit_list ⟨m.1, _⟩ m.2 + +theorem size_insertManyIfNewUnit_list_le [EquivBEq α] [LawfulHashable α] + {l : List α} : + (insertManyIfNewUnit m l).size ≤ m.size + l.length := + Raw₀.Const.size_insertManyIfNewUnit_list_le ⟨m.1, _⟩ m.2 + +@[simp] +theorem isEmpty_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} : + (insertManyIfNewUnit m l).isEmpty = (m.isEmpty && l.isEmpty) := + Raw₀.Const.isEmpty_insertManyIfNewUnit_list ⟨m.1, _⟩ m.2 + +theorem get?_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + get? (insertManyIfNewUnit m l) k = + if k ∈ m ∨ l.contains k then some () else none := + Raw₀.Const.get?_insertManyIfNewUnit_list ⟨m.1, _⟩ m.2 + +theorem get_insertManyIfNewUnit_list + {l : List α} {k : α} {h} : + get (insertManyIfNewUnit m l) k h = () := + Raw₀.Const.get_insertManyIfNewUnit_list ⟨m.1, _⟩ + +theorem get!_insertManyIfNewUnit_list + {l : List α} {k : α} : + get! (insertManyIfNewUnit m l) k = () := + Raw₀.Const.get!_insertManyIfNewUnit_list ⟨m.1, _⟩ + +theorem getD_insertManyIfNewUnit_list + {l : List α} {k : α} {fallback : Unit} : + getD (insertManyIfNewUnit m l) k fallback = () := by + simp + +end Const + +end DHashMap + +namespace DHashMap + +@[simp] +theorem ofList_nil : + ofList ([] : List ((a : α) × (β a))) = ∅ := + Subtype.eq (congrArg Subtype.val (Raw₀.insertMany_empty_list_nil (α := α)) :) + +@[simp] +theorem ofList_singleton {k : α} {v : β k} : + ofList [⟨k, v⟩] = (∅: DHashMap α β).insert k v := + Subtype.eq (congrArg Subtype.val (Raw₀.insertMany_empty_list_singleton (α := α)) :) + +theorem ofList_cons {k : α} {v : β k} {tl : List ((a : α) × (β a))} : + ofList (⟨k, v⟩ :: tl) = ((∅ : DHashMap α β).insert k v).insertMany tl := + Subtype.eq (congrArg Subtype.val (Raw₀.insertMany_empty_list_cons (α := α)) :) + +@[simp] +theorem contains_ofList [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} : + (ofList l).contains k = (l.map Sigma.fst).contains k := + Raw₀.contains_insertMany_empty_list + +@[simp] +theorem mem_ofList [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} : + k ∈ ofList l ↔ (l.map Sigma.fst).contains k := by + simp [mem_iff_contains] + +theorem get?_ofList_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (ofList l).get? k = none := + Raw₀.get?_insertMany_empty_list_of_contains_eq_false contains_eq_false + +theorem get?_ofList_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (ofList l).get? k' = some (cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v) := + Raw₀.get?_insertMany_empty_list_of_mem k_beq distinct mem + +theorem get_ofList_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) + {h} : + (ofList l).get k' h = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := + Raw₀.get_insertMany_empty_list_of_mem k_beq distinct mem + +theorem get!_ofList_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} [Inhabited (β k)] + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (ofList l).get! k = default := + Raw₀.get!_insertMany_empty_list_of_contains_eq_false contains_eq_false + +theorem get!_ofList_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} [Inhabited (β k')] + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (ofList l).get! k' = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := + Raw₀.get!_insertMany_empty_list_of_mem k_beq distinct mem + +theorem getD_ofList_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} {fallback : β k} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (ofList l).getD k fallback = fallback := + Raw₀.getD_insertMany_empty_list_of_contains_eq_false contains_eq_false + +theorem getD_ofList_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} {fallback : β k'} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (ofList l).getD k' fallback = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := + Raw₀.getD_insertMany_empty_list_of_mem k_beq distinct mem + +theorem getKey?_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (ofList l).getKey? k = none := + Raw₀.getKey?_insertMany_empty_list_of_contains_eq_false contains_eq_false + +theorem getKey?_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (ofList l).getKey? k' = some k := + Raw₀.getKey?_insertMany_empty_list_of_mem k_beq distinct mem + +theorem getKey_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) + {h} : + (ofList l).getKey k' h = k := + Raw₀.getKey_insertMany_empty_list_of_mem k_beq distinct mem + +theorem getKey!_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (ofList l).getKey! k = default := + Raw₀.getKey!_insertMany_empty_list_of_contains_eq_false contains_eq_false + +theorem getKey!_ofList_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (ofList l).getKey! k' = k := + Raw₀.getKey!_insertMany_empty_list_of_mem k_beq distinct mem + +theorem getKeyD_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k fallback : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (ofList l).getKeyD k fallback = fallback := + Raw₀.getKeyD_insertMany_empty_list_of_contains_eq_false contains_eq_false + +theorem getKeyD_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (ofList l).getKeyD k' fallback = k := + Raw₀.getKeyD_insertMany_empty_list_of_mem k_beq distinct mem + +theorem size_ofList [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (ofList l).size = l.length := + Raw₀.size_insertMany_empty_list distinct + +theorem size_ofList_le [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} : + (ofList l).size ≤ l.length := + Raw₀.size_insertMany_empty_list_le + +@[simp] +theorem isEmpty_ofList [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} : + (ofList l).isEmpty = l.isEmpty := + Raw₀.isEmpty_insertMany_empty_list + +namespace Const + +variable {β : Type v} + +@[simp] +theorem ofList_nil : + ofList ([] : List (α × β)) = ∅ := + Subtype.eq (congrArg Subtype.val (Raw₀.Const.insertMany_empty_list_nil (α:= α)) :) + +@[simp] +theorem ofList_singleton {k : α} {v : β} : + ofList [⟨k, v⟩] = (∅ : DHashMap α (fun _ => β)).insert k v := + Subtype.eq (congrArg Subtype.val (Raw₀.Const.insertMany_empty_list_singleton (α:= α)) :) + +theorem ofList_cons {k : α} {v : β} {tl : List (α × β)} : + ofList (⟨k, v⟩ :: tl) = insertMany ((∅ : DHashMap α (fun _ => β)).insert k v) tl := + Subtype.eq (congrArg Subtype.val (Raw₀.Const.insertMany_empty_list_cons (α:= α)) :) + +@[simp] +theorem contains_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + (ofList l).contains k = (l.map Prod.fst).contains k := + Raw₀.Const.contains_insertMany_empty_list + +@[simp] +theorem mem_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + k ∈ ofList l ↔ (l.map Prod.fst).contains k := by + simp [mem_iff_contains] + +theorem get?_ofList_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + get? (ofList l) k = none := + Raw₀.Const.get?_insertMany_empty_list_of_contains_eq_false contains_eq_false + +theorem get?_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + get? (ofList l) k' = some v := + Raw₀.Const.get?_insertMany_empty_list_of_mem k_beq distinct mem + +theorem get_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) + {h} : + get (ofList l) k' h = v := + Raw₀.Const.get_insertMany_empty_list_of_mem k_beq distinct mem + +theorem get!_ofList_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} [Inhabited β] + (contains_eq_false : (l.map Prod.fst).contains k = false) : + get! (ofList l) k = (default : β) := + Raw₀.Const.get!_insertMany_empty_list_of_contains_eq_false contains_eq_false + +theorem get!_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} [Inhabited β] + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + get! (ofList l) k' = v := + Raw₀.Const.get!_insertMany_empty_list_of_mem k_beq distinct mem + +theorem getD_ofList_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} {fallback : β} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + getD (ofList l) k fallback = fallback := + Raw₀.Const.getD_insertMany_empty_list_of_contains_eq_false contains_eq_false + +theorem getD_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} {fallback : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + getD (ofList l) k' fallback = v := + Raw₀.Const.getD_insertMany_empty_list_of_mem k_beq distinct mem + +theorem getKey?_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l).getKey? k = none := + Raw₀.Const.getKey?_insertMany_empty_list_of_contains_eq_false contains_eq_false + +theorem getKey?_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (ofList l).getKey? k' = some k := + Raw₀.Const.getKey?_insertMany_empty_list_of_mem k_beq distinct mem + +theorem getKey_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) + {h} : + (ofList l).getKey k' h = k := + Raw₀.Const.getKey_insertMany_empty_list_of_mem k_beq distinct mem + +theorem getKey!_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l).getKey! k = default := + Raw₀.Const.getKey!_insertMany_empty_list_of_contains_eq_false contains_eq_false + +theorem getKey!_ofList_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (ofList l).getKey! k' = k := + Raw₀.Const.getKey!_insertMany_empty_list_of_mem k_beq distinct mem + +theorem getKeyD_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k fallback : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l).getKeyD k fallback = fallback := + Raw₀.Const.getKeyD_insertMany_empty_list_of_contains_eq_false contains_eq_false + +theorem getKeyD_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (ofList l).getKeyD k' fallback = k := + Raw₀.Const.getKeyD_insertMany_empty_list_of_mem k_beq distinct mem + +theorem size_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (ofList l).size = l.length := + Raw₀.Const.size_insertMany_empty_list distinct + +theorem size_ofList_le [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (ofList l).size ≤ l.length := + Raw₀.Const.size_insertMany_empty_list_le + +@[simp] +theorem isEmpty_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (ofList l).isEmpty = l.isEmpty := + Raw₀.Const.isEmpty_insertMany_empty_list + +@[simp] +theorem unitOfList_nil : + unitOfList ([] : List α) = ∅ := + Subtype.eq (congrArg Subtype.val (Raw₀.Const.insertManyIfNewUnit_empty_list_nil (α := α)) :) + +@[simp] +theorem unitOfList_singleton {k : α} : + unitOfList [k] = (∅ : DHashMap α (fun _ => Unit)).insertIfNew k () := + Subtype.eq (congrArg Subtype.val (Raw₀.Const.insertManyIfNewUnit_empty_list_singleton (α := α)) :) + +theorem unitOfList_cons {hd : α} {tl : List α} : + unitOfList (hd :: tl) = + insertManyIfNewUnit ((∅ : DHashMap α (fun _ => Unit)).insertIfNew hd ()) tl := + Subtype.eq (congrArg Subtype.val (Raw₀.Const.insertManyIfNewUnit_empty_list_cons (α := α)) :) + +@[simp] +theorem contains_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (unitOfList l).contains k = l.contains k := + Raw₀.Const.contains_insertManyIfNewUnit_empty_list + +@[simp] +theorem mem_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + k ∈ unitOfList l ↔ l.contains k := by + simp [mem_iff_contains] + +theorem getKey?_unitOfList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (contains_eq_false : l.contains k = false) : + getKey? (unitOfList l) k = none := + Raw₀.Const.getKey?_insertManyIfNewUnit_empty_list_of_contains_eq_false contains_eq_false + +theorem getKey?_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getKey? (unitOfList l) k' = some k := + Raw₀.Const.getKey?_insertManyIfNewUnit_empty_list_of_mem k_beq distinct mem + +theorem getKey_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) {h} : + getKey (unitOfList l) k' h = k := + Raw₀.Const.getKey_insertManyIfNewUnit_empty_list_of_mem k_beq distinct mem + +theorem getKey!_unitOfList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k : α} + (contains_eq_false : l.contains k = false) : + getKey! (unitOfList l) k = default := + Raw₀.Const.getKey!_insertManyIfNewUnit_empty_list_of_contains_eq_false contains_eq_false + +theorem getKey!_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + getKey! (unitOfList l) k' = k := + Raw₀.Const.getKey!_insertManyIfNewUnit_empty_list_of_mem k_beq distinct mem + +theorem getKeyD_unitOfList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k fallback : α} + (contains_eq_false : l.contains k = false) : + getKeyD (unitOfList l) k fallback = fallback := + Raw₀.Const.getKeyD_insertManyIfNewUnit_empty_list_of_contains_eq_false contains_eq_false + +theorem getKeyD_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + getKeyD (unitOfList l) k' fallback = k := + Raw₀.Const.getKeyD_insertManyIfNewUnit_empty_list_of_mem k_beq distinct mem + +theorem size_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (unitOfList l).size = l.length := + Raw₀.Const.size_insertManyIfNewUnit_empty_list distinct + +theorem size_unitOfList_le [EquivBEq α] [LawfulHashable α] + {l : List α} : + (unitOfList l).size ≤ l.length := + Raw₀.Const.size_insertManyIfNewUnit_empty_list_le + +@[simp] +theorem isEmpty_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} : + (unitOfList l).isEmpty = l.isEmpty := + Raw₀.Const.isEmpty_insertManyIfNewUnit_empty_list + +@[simp] +theorem get?_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + get? (unitOfList l) k = + if l.contains k then some () else none := + Raw₀.Const.get?_insertManyIfNewUnit_empty_list + +@[simp] +theorem get_unitOfList + {l : List α} {k : α} {h} : + get (unitOfList l) k h = () := + Raw₀.Const.get_insertManyIfNewUnit_empty_list + +@[simp] +theorem get!_unitOfList + {l : List α} {k : α} : + get! (unitOfList l) k = () := + Raw₀.Const.get!_insertManyIfNewUnit_empty_list + +@[simp] +theorem getD_unitOfList + {l : List α} {k : α} {fallback : Unit} : + getD (unitOfList l) k fallback = () := by + simp + +end Const + end Std.DHashMap diff --git a/src/Std/Data/DHashMap/Raw.lean b/src/Std/Data/DHashMap/Raw.lean index 5ca1cdc1a588..a5acdd419e70 100644 --- a/src/Std/Data/DHashMap/Raw.lean +++ b/src/Std/Data/DHashMap/Raw.lean @@ -94,7 +94,7 @@ Checks whether a key is present in a map, and unconditionally inserts a value fo Equivalent to (but potentially faster than) calling `contains` followed by `insert`. -/ @[inline] def containsThenInsert [BEq α] [Hashable α] (m : Raw α β) (a : α) (b : β a) : - Bool × Raw α β:= + Bool × Raw α β := if h : 0 < m.buckets.size then let ⟨replaced, ⟨r, _⟩⟩ := Raw₀.containsThenInsert ⟨m, h⟩ a b ⟨replaced, r⟩ @@ -422,29 +422,12 @@ This is mainly useful to implement `HashSet.insertMany`, so if you are consideri (Raw₀.Const.insertManyIfNewUnit ⟨m, h⟩ l).1 else m -- will never happen for well-formed inputs -/-- Creates a hash map from a list of mappings. If the same key appears multiple times, the last -occurrence takes precedence. -/ -@[inline] def ofList [BEq α] [Hashable α] (l : List ((a : α) × β a)) : Raw α β := - insertMany ∅ l - /-- Computes the union of the given hash maps, by traversing `m₂` and inserting its elements into `m₁`. -/ @[inline] def union [BEq α] [Hashable α] (m₁ m₂ : Raw α β) : Raw α β := m₂.fold (init := m₁) fun acc x => acc.insert x instance [BEq α] [Hashable α] : Union (Raw α β) := ⟨union⟩ -@[inline, inherit_doc Raw.ofList] def Const.ofList {β : Type v} [BEq α] [Hashable α] - (l : List (α × β)) : Raw α (fun _ => β) := - Const.insertMany ∅ l - -/-- Creates a hash map from a list of keys, associating the value `()` with each key. - -This is mainly useful to implement `HashSet.ofList`, so if you are considering using this, -`HashSet` or `HashSet.Raw` might be a better fit for you. -/ -@[inline] def Const.unitOfList [BEq α] [Hashable α] (l : List α) : - Raw α (fun _ => Unit) := - Const.insertManyIfNewUnit ∅ l - /-- Creates a hash map from an array of keys, associating the value `()` with each key. This is mainly useful to implement `HashSet.ofArray`, so if you are considering using this, @@ -470,6 +453,23 @@ end Unverified @[inline] def keys (m : Raw α β) : List α := m.foldRev (fun acc k _ => k :: acc) [] +/-- Creates a hash map from a list of mappings. If the same key appears multiple times, the last +occurrence takes precedence. -/ +@[inline] def ofList [BEq α] [Hashable α] (l : List ((a : α) × β a)) : Raw α β := + insertMany ∅ l + +@[inline, inherit_doc Raw.ofList] def Const.ofList {β : Type v} [BEq α] [Hashable α] + (l : List (α × β)) : Raw α (fun _ => β) := + Const.insertMany ∅ l + +/-- Creates a hash map from a list of keys, associating the value `()` with each key. + +This is mainly useful to implement `HashSet.ofList`, so if you are considering using this, +`HashSet` or `HashSet.Raw` might be a better fit for you. -/ +@[inline] def Const.unitOfList [BEq α] [Hashable α] (l : List α) : + Raw α (fun _ => Unit) := + Const.insertManyIfNewUnit ∅ l + section WF /-- diff --git a/src/Std/Data/DHashMap/RawLemmas.lean b/src/Std/Data/DHashMap/RawLemmas.lean index 42d4db498753..147a2ce3bd3d 100644 --- a/src/Std/Data/DHashMap/RawLemmas.lean +++ b/src/Std/Data/DHashMap/RawLemmas.lean @@ -58,7 +58,11 @@ private def baseNames : Array Name := ``getKey?_eq, ``getKey?_val, ``getKey_eq, ``getKey_val, ``getKey!_eq, ``getKey!_val, - ``getKeyD_eq, ``getKeyD_val] + ``getKeyD_eq, ``getKeyD_val, + ``insertMany_eq, ``insertMany_val, + ``Const.insertMany_eq, ``Const.insertMany_val, + ``Const.insertManyIfNewUnit_eq, ``Const.insertManyIfNewUnit_val, + ``ofList_eq, ``Const.ofList_eq, ``Const.unitOfList_eq] /-- Internal implementation detail of the hash map -/ scoped syntax "simp_to_raw" ("using" term)? : tactic @@ -765,7 +769,7 @@ theorem getKey!_eq_default_of_contains_eq_false [EquivBEq α] [LawfulHashable α m.contains a = false → m.getKey! a = default := by simp_to_raw using Raw₀.getKey!_eq_default -theorem getKey!_eq_default [EquivBEq α] [LawfulHashable α] [Inhabited α] (h : m.WF) {a : α}: +theorem getKey!_eq_default [EquivBEq α] [LawfulHashable α] [Inhabited α] (h : m.WF) {a : α} : ¬a ∈ m → m.getKey! a = default := by simpa [mem_iff_contains] using getKey!_eq_default_of_contains_eq_false h @@ -1028,7 +1032,7 @@ theorem length_keys [EquivBEq α] [LawfulHashable α] (h : m.WF) : simp_to_raw using Raw₀.length_keys ⟨m, h.size_buckets_pos⟩ h @[simp] -theorem isEmpty_keys [EquivBEq α] [LawfulHashable α] (h : m.WF): +theorem isEmpty_keys [EquivBEq α] [LawfulHashable α] (h : m.WF) : m.keys.isEmpty = m.isEmpty := by simp_to_raw using Raw₀.isEmpty_keys ⟨m, h.size_buckets_pos⟩ @@ -1039,7 +1043,7 @@ theorem contains_keys [EquivBEq α] [LawfulHashable α] (h : m.WF) {k : α} : @[simp] theorem mem_keys [LawfulBEq α] [LawfulHashable α] (h : m.WF) {k : α} : - k ∈ m.keys ↔ k ∈ m := by + k ∈ m.keys ↔ k ∈ m := by rw [mem_iff_contains] simp_to_raw using Raw₀.mem_keys ⟨m, _⟩ h @@ -1047,6 +1051,931 @@ theorem distinct_keys [EquivBEq α] [LawfulHashable α] (h : m.WF) : m.keys.Pairwise (fun a b => (a == b) = false) := by simp_to_raw using Raw₀.distinct_keys ⟨m, h.size_buckets_pos⟩ h +@[simp] +theorem insertMany_nil [EquivBEq α] [LawfulHashable α] (h : m.WF) : + m.insertMany [] = m := by + simp_to_raw + rw [Raw₀.insertMany_nil] + +@[simp] +theorem insertMany_list_singleton {k : α} {v : β k} [EquivBEq α] [LawfulHashable α] (h : m.WF) : + m.insertMany [⟨k, v⟩] = m.insert k v := by + simp_to_raw + rw [Raw₀.insertMany_list_singleton] + +theorem insertMany_cons {l : List ((a : α) × β a)} {k : α} {v : β k} [EquivBEq α] [LawfulHashable α] + (h : m.WF) : + m.insertMany (⟨k, v⟩ :: l) = (m.insert k v).insertMany l := by + simp_to_raw + rw [Raw₀.insertMany_cons] + +@[simp] +theorem contains_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} {k : α} : + (m.insertMany l).contains k = (m.contains k || (l.map Sigma.fst).contains k) := by + simp_to_raw using Raw₀.contains_insertMany_list + +@[simp] +theorem mem_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} {k : α} : + k ∈ (m.insertMany l) ↔ k ∈ m ∨ (l.map Sigma.fst).contains k := by + simp [mem_iff_contains, contains_insertMany_list h] + +theorem mem_of_mem_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} {k : α} : + k ∈ (m.insertMany l) → (l.map Sigma.fst).contains k = false → k ∈ m := by + simp only [mem_iff_contains] + simp_to_raw using Raw₀.contains_of_contains_insertMany_list + +theorem get?_insertMany_list_of_contains_eq_false [LawfulBEq α] (h : m.WF) + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).get? k = m.get? k := by + simp_to_raw using Raw₀.get?_insertMany_list_of_contains_eq_false + +theorem get?_insertMany_list_of_mem [LawfulBEq α] (h : m.WF) + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (m.insertMany l).get? k' = some (cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v) := by + simp_to_raw using Raw₀.get?_insertMany_list_of_mem + +theorem get_insertMany_list_of_contains_eq_false [LawfulBEq α] (h : m.WF) + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) + {h'} : + (m.insertMany l).get k h' = + m.get k (mem_of_mem_insertMany_list h h' contains_eq_false) := by + simp_to_raw using Raw₀.get_insertMany_list_of_contains_eq_false + +theorem get_insertMany_list_of_mem [LawfulBEq α] (h : m.WF) + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) + {h'} : + (m.insertMany l).get k' h' = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := by + simp_to_raw using Raw₀.get_insertMany_list_of_mem + +theorem get!_insertMany_list_of_contains_eq_false [LawfulBEq α] (h : m.WF) + {l : List ((a : α) × β a)} {k : α} [Inhabited (β k)] + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).get! k = m.get! k := by + simp_to_raw using Raw₀.get!_insertMany_list_of_contains_eq_false + +theorem get!_insertMany_list_of_mem [LawfulBEq α] (h : m.WF) + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} [Inhabited (β k')] + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (m.insertMany l).get! k' = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := by + simp_to_raw using Raw₀.get!_insertMany_list_of_mem + +theorem getD_insertMany_list_of_contains_eq_false [LawfulBEq α] (h : m.WF) + {l : List ((a : α) × β a)} {k : α} {fallback : β k} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).getD k fallback = m.getD k fallback := by + simp_to_raw using Raw₀.getD_insertMany_list_of_contains_eq_false + +theorem getD_insertMany_list_of_mem [LawfulBEq α] (h : m.WF) + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} {fallback : β k'} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (m.insertMany l).getD k' fallback = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := by + simp_to_raw using Raw₀.getD_insertMany_list_of_mem + +theorem getKey?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).getKey? k = m.getKey? k := by + simp_to_raw using Raw₀.getKey?_insertMany_list_of_contains_eq_false + +theorem getKey?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (m.insertMany l).getKey? k' = some k := by + simp_to_raw using Raw₀.getKey?_insertMany_list_of_mem + +theorem getKey_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) + {h'} : + (m.insertMany l).getKey k h' = + m.getKey k (mem_of_mem_insertMany_list h h' contains_eq_false) := by + simp_to_raw using Raw₀.getKey_insertMany_list_of_contains_eq_false + +theorem getKey_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) + {h'} : + (m.insertMany l).getKey k' h' = k := by + simp_to_raw using Raw₀.getKey_insertMany_list_of_mem + +theorem getKey!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] [Inhabited α] + (h : m.WF) {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).getKey! k = m.getKey! k := by + simp_to_raw using Raw₀.getKey!_insertMany_list_of_contains_eq_false + +theorem getKey!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] (h : m.WF) + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (m.insertMany l).getKey! k' = k := by + simp_to_raw using Raw₀.getKey!_insertMany_list_of_mem + +theorem getKeyD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} {k fallback : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (m.insertMany l).getKeyD k fallback = m.getKeyD k fallback := by + simp_to_raw using Raw₀.getKeyD_insertMany_list_of_contains_eq_false + +theorem getKeyD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (m.insertMany l).getKeyD k' fallback = k := by + simp_to_raw using Raw₀.getKeyD_insertMany_list_of_mem + +theorem size_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (∀ (a : α), a ∈ m → (l.map Sigma.fst).contains a = false) → + (m.insertMany l).size = m.size + l.length := by + simp only [mem_iff_contains] + simp_to_raw using Raw₀.size_insertMany_list + +theorem size_le_size_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} : + m.size ≤ (m.insertMany l).size := by + simp_to_raw using Raw₀.size_le_size_insertMany_list ⟨m, _⟩ + +theorem size_insertMany_list_le [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} : + (m.insertMany l).size ≤ m.size + l.length := by + simp_to_raw using Raw₀.size_insertMany_list_le + +@[simp] +theorem isEmpty_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List ((a : α) × β a)} : + (m.insertMany l).isEmpty = (m.isEmpty && l.isEmpty) := by + simp_to_raw using Raw₀.isEmpty_insertMany_list + +namespace Const + +variable {β : Type v} {m : Raw α (fun _ => β)} + +@[simp] +theorem insertMany_nil (h : m.WF) : + insertMany m [] = m := by + simp_to_raw + rw [Raw₀.Const.insertMany_nil] + +@[simp] +theorem insertMany_list_singleton (h : m.WF) + {k : α} {v : β} : + insertMany m [⟨k, v⟩] = m.insert k v := by + simp_to_raw + rw [Raw₀.Const.insertMany_list_singleton] + +theorem insertMany_cons (h : m.WF) {l : List (α × β)} + {k : α} {v : β} : + insertMany m (⟨k, v⟩ :: l) = insertMany (m.insert k v) l := by + simp_to_raw + rw [Raw₀.Const.insertMany_cons] + +@[simp] +theorem contains_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k : α} : + (insertMany m l).contains k = (m.contains k || (l.map Prod.fst).contains k) := by + simp_to_raw using Raw₀.Const.contains_insertMany_list + +@[simp] +theorem mem_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k : α} : + k ∈ insertMany m l ↔ k ∈ m ∨ (l.map Prod.fst).contains k := by + simp [mem_iff_contains, contains_insertMany_list h] + +theorem mem_of_mem_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k : α} : + k ∈ insertMany m l → (l.map Prod.fst).contains k = false → k ∈ m := by + simp only [mem_iff_contains] + simp_to_raw using Raw₀.Const.contains_of_contains_insertMany_list + +theorem getKey?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l).getKey? k = m.getKey? k := by + simp_to_raw using Raw₀.Const.getKey?_insertMany_list_of_contains_eq_false + +theorem getKey?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).getKey? k' = some k := by + simp_to_raw using Raw₀.Const.getKey?_insertMany_list_of_mem + +theorem getKey_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) + {h'} : + (insertMany m l).getKey k h' = + m.getKey k (mem_of_mem_insertMany_list h h' contains_eq_false) := by + simp_to_raw using Raw₀.Const.getKey_insertMany_list_of_contains_eq_false + +theorem getKey_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) + {h'} : + (insertMany m l).getKey k' h' = k := by + simp_to_raw using Raw₀.Const.getKey_insertMany_list_of_mem + +theorem getKey!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] [Inhabited α] + (h : m.WF) {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l).getKey! k = m.getKey! k := by + simp_to_raw using Raw₀.Const.getKey!_insertMany_list_of_contains_eq_false + +theorem getKey!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] (h : m.WF) + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).getKey! k' = k := by + simp_to_raw using Raw₀.Const.getKey!_insertMany_list_of_mem + +theorem getKeyD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k fallback : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l).getKeyD k fallback = m.getKeyD k fallback := by + simp_to_raw using Raw₀.Const.getKeyD_insertMany_list_of_contains_eq_false + +theorem getKeyD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).getKeyD k' fallback = k := by + simp_to_raw using Raw₀.Const.getKeyD_insertMany_list_of_mem + +theorem size_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (∀ (a : α), a ∈ m → (l.map Prod.fst).contains a = false) → + (insertMany m l).size = m.size + l.length := by + simp [mem_iff_contains] + simp_to_raw using Raw₀.Const.size_insertMany_list + +theorem size_le_size_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} : + m.size ≤ (insertMany m l).size := by + simp_to_raw using Raw₀.Const.size_le_size_insertMany_list ⟨m, _⟩ + +theorem size_insertMany_list_le [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} : + (insertMany m l).size ≤ m.size + l.length := by + simp_to_raw using Raw₀.Const.size_insertMany_list_le + +@[simp] +theorem isEmpty_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} : + (insertMany m l).isEmpty = (m.isEmpty && l.isEmpty) := by + simp_to_raw using Raw₀.Const.isEmpty_insertMany_list + +theorem get?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + get? (insertMany m l) k = get? m k := by + simp_to_raw using Raw₀.Const.get?_insertMany_list_of_contains_eq_false + +theorem get?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + get? (insertMany m l) k' = v := by + simp_to_raw using Raw₀.Const.get?_insertMany_list_of_mem + +theorem get_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) + {h'} : + get (insertMany m l) k h' = + get m k (mem_of_mem_insertMany_list h h' contains_eq_false) := by + simp_to_raw using Raw₀.Const.get_insertMany_list_of_contains_eq_false + +theorem get_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l){h'} : + get (insertMany m l) k' h' = v := by + simp_to_raw using Raw₀.Const.get_insertMany_list_of_mem + +theorem get!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited β] (h : m.WF) {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + get! (insertMany m l) k = get! m k := by + simp_to_raw using Raw₀.Const.get!_insertMany_list_of_contains_eq_false + +theorem get!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited β] (h : m.WF) + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + get! (insertMany m l) k' = v := by + simp_to_raw using Raw₀.Const.get!_insertMany_list_of_mem + +theorem getD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k : α} {fallback : β} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + getD (insertMany m l) k fallback = getD m k fallback := by + simp_to_raw using Raw₀.Const.getD_insertMany_list_of_contains_eq_false + +theorem getD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v fallback : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + getD (insertMany m l) k' fallback = v := by + simp_to_raw using Raw₀.Const.getD_insertMany_list_of_mem + +variable {m : Raw α (fun _ => Unit)} + +@[simp] +theorem insertManyIfNewUnit_nil (h : m.WF) : + insertManyIfNewUnit m [] = m := by + simp_to_raw + rw [Raw₀.Const.insertManyIfNewUnit_nil] + +@[simp] +theorem insertManyIfNewUnit_list_singleton {k : α} (h : m.WF) : + insertManyIfNewUnit m [k] = m.insertIfNew k () := by + simp_to_raw + rw [Raw₀.Const.insertManyIfNewUnit_list_singleton] + +theorem insertManyIfNewUnit_cons (h : m.WF) {l : List α} {k : α} : + insertManyIfNewUnit m (k :: l) = insertManyIfNewUnit (m.insertIfNew k ()) l := by + simp_to_raw + rw [Raw₀.Const.insertManyIfNewUnit_cons] + +@[simp] +theorem contains_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} {k : α} : + (insertManyIfNewUnit m l).contains k = (m.contains k || l.contains k) := by + simp_to_raw using Raw₀.Const.contains_insertManyIfNewUnit_list + +@[simp] +theorem mem_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} {k : α} : + k ∈ insertManyIfNewUnit m l ↔ k ∈ m ∨ l.contains k := by + simp [mem_iff_contains, contains_insertManyIfNewUnit_list h] + +theorem mem_of_mem_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} {k : α} (contains_eq_false : l.contains k = false) : + k ∈ insertManyIfNewUnit m l → k ∈ m := by + simp only [mem_iff_contains] + simp_to_raw using Raw₀.Const.contains_of_contains_insertManyIfNewUnit_list + +theorem getKey?_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] (h : m.WF) {l : List α} {k : α} : + ¬ k ∈ m → l.contains k = false → + getKey? (insertManyIfNewUnit m l) k = none := by + simp only [mem_iff_contains, Bool.not_eq_true] + simp_to_raw using Raw₀.Const.getKey?_insertManyIfNewUnit_list_of_contains_eq_false_of_contains_eq_false + +theorem getKey?_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k k' : α} (k_beq : k == k') : + ¬ k ∈ m → l.Pairwise (fun a b => (a == b) = false) → k ∈ l → + getKey? (insertManyIfNewUnit m l) k' = some k := by + simp only [mem_iff_contains, Bool.not_eq_true] + simp_to_raw using Raw₀.Const.getKey?_insertManyIfNewUnit_list_of_contains_eq_false_of_mem + +theorem getKey?_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k : α} : + k ∈ m → getKey? (insertManyIfNewUnit m l) k = getKey? m k := by + simp only [mem_iff_contains] + simp_to_raw using Raw₀.Const.getKey?_insertManyIfNewUnit_list_of_contains + +theorem getKey_insertManyIfNewUnit_list_of_mem + [EquivBEq α] [LawfulHashable α] (h : m.WF) {l : List α} {k : α} {h'} (mem : k ∈ m) : + getKey (insertManyIfNewUnit m l) k h' = getKey m k mem := by + simp_to_raw using Raw₀.Const.getKey_insertManyIfNewUnit_list_of_contains + +theorem getKey_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} + {k k' : α} (k_beq : k == k') {h'} : + ¬ k ∈ m → l.Pairwise (fun a b => (a == b) = false) → k ∈ l → + getKey (insertManyIfNewUnit m l) k' h' = k := by + simp only [mem_iff_contains, Bool.not_eq_true] + simp_to_raw using Raw₀.Const.getKey_insertManyIfNewUnit_list_of_contains_eq_false_of_mem + +theorem getKey!_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] [Inhabited α] (h : m.WF) {l : List α} {k : α} : + ¬ k ∈ m → l.contains k = false → getKey! (insertManyIfNewUnit m l) k = default := by + simp only [mem_iff_contains, Bool.not_eq_true] + simp_to_raw using + Raw₀.Const.getKey!_insertManyIfNewUnit_list_of_contains_eq_false_of_contains_eq_false + +theorem getKey!_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] (h : m.WF) {l : List α} {k k' : α} (k_beq : k == k') : + ¬ k ∈ m → l.Pairwise (fun a b => (a == b) = false) → k ∈ l → + getKey! (insertManyIfNewUnit m l) k' = k := by + simp only [mem_iff_contains, Bool.not_eq_true] + simp_to_raw using Raw₀.Const.getKey!_insertManyIfNewUnit_list_of_contains_eq_false_of_mem + +theorem getKey!_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] (h : m.WF) {l : List α} {k : α} : + k ∈ m → getKey! (insertManyIfNewUnit m l) k = getKey! m k := by + simp only [mem_iff_contains] + simp_to_raw using Raw₀.Const.getKey!_insertManyIfNewUnit_list_of_contains + +theorem getKeyD_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] (h : m.WF) {l : List α} {k fallback : α} : + ¬ k ∈ m → l.contains k = false → + getKeyD (insertManyIfNewUnit m l) k fallback = fallback := by + simp only [mem_iff_contains, Bool.not_eq_true] + simp_to_raw using + Raw₀.Const.getKeyD_insertManyIfNewUnit_list_of_contains_eq_false_of_contains_eq_false + +theorem getKeyD_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k k' fallback : α} (k_beq : k == k') : + ¬ k ∈ m → l.Pairwise (fun a b => (a == b) = false) → k ∈ l → + getKeyD (insertManyIfNewUnit m l) k' fallback = k := by + simp only [mem_iff_contains, Bool.not_eq_true] + simp_to_raw using Raw₀.Const.getKeyD_insertManyIfNewUnit_list_of_contains_eq_false_of_mem + +theorem getKeyD_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k fallback : α} : + k ∈ m → getKeyD (insertManyIfNewUnit m l) k fallback = getKeyD m k fallback := by + simp only [mem_iff_contains] + simp_to_raw using Raw₀.Const.getKeyD_insertManyIfNewUnit_list_of_contains + +theorem size_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (∀ (a : α), a ∈ m → l.contains a = false) → + (insertManyIfNewUnit m l).size = m.size + l.length := by + simp only [mem_iff_contains] + simp_to_raw using Raw₀.Const.size_insertManyIfNewUnit_list + +theorem size_le_size_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} : + m.size ≤ (insertManyIfNewUnit m l).size := by + simp_to_raw using Raw₀.Const.size_le_size_insertManyIfNewUnit_list ⟨m, _⟩ + +theorem size_insertManyIfNewUnit_list_le [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} : + (insertManyIfNewUnit m l).size ≤ m.size + l.length := by + simp_to_raw using Raw₀.Const.size_insertManyIfNewUnit_list_le + +@[simp] +theorem isEmpty_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} : + (insertManyIfNewUnit m l).isEmpty = (m.isEmpty && l.isEmpty) := by + simp_to_raw using Raw₀.Const.isEmpty_insertManyIfNewUnit_list + +@[simp] +theorem get?_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} {k : α} : + get? (insertManyIfNewUnit m l) k = + if k ∈ m ∨ l.contains k then some () else none := by + simp only [mem_iff_contains] + simp_to_raw using Raw₀.Const.get?_insertManyIfNewUnit_list + +@[simp] +theorem get_insertManyIfNewUnit_list + {l : List α} {k : α} {h} : + get (insertManyIfNewUnit m l) k h = () := by + simp + +@[simp] +theorem get!_insertManyIfNewUnit_list + {l : List α} {k : α} : + get! (insertManyIfNewUnit m l) k = () := by + simp + +@[simp] +theorem getD_insertManyIfNewUnit_list + {l : List α} {k : α} {fallback : Unit} : + getD (insertManyIfNewUnit m l) k fallback = () := by + simp + +end Const + +end Raw + +namespace Raw + +variable [BEq α] [Hashable α] + +open Internal.Raw Internal.Raw₀ + +@[simp] +theorem ofList_nil : + ofList ([] : List ((a : α) × (β a))) = ∅ := by + simp_to_raw + rw [Raw₀.insertMany_empty_list_nil] + +@[simp] +theorem ofList_singleton {k : α} {v : β k} : + ofList [⟨k, v⟩] = (∅ : Raw α β).insert k v := by + simp_to_raw + rw [Raw₀.insertMany_empty_list_singleton] + +theorem ofList_cons [EquivBEq α] [LawfulHashable α] {k : α} {v : β k} {tl : List ((a : α) × (β a))} : + ofList (⟨k, v⟩ :: tl) = ((∅ : Raw α β).insert k v).insertMany tl := by + simp_to_raw + rw [Raw₀.insertMany_empty_list_cons] + +@[simp] +theorem contains_ofList [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} : + (ofList l).contains k = (l.map Sigma.fst).contains k := by + simp_to_raw using Raw₀.contains_insertMany_empty_list + +@[simp] +theorem mem_ofList [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} : + k ∈ ofList l ↔ (l.map Sigma.fst).contains k := by + simp [mem_iff_contains] + +theorem get?_ofList_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (ofList l).get? k = none := by + simp_to_raw using Raw₀.get?_insertMany_empty_list_of_contains_eq_false + +theorem get?_ofList_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (ofList l).get? k' = some (cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v) := by + simp_to_raw using Raw₀.get?_insertMany_empty_list_of_mem + +theorem get_ofList_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) + {h} : + (ofList l).get k' h = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := by + simp_to_raw using Raw₀.get_insertMany_empty_list_of_mem + +theorem get!_ofList_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} [Inhabited (β k)] + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (ofList l).get! k = default := by + simp_to_raw using get!_insertMany_empty_list_of_contains_eq_false + +theorem get!_ofList_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} [Inhabited (β k')] + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (ofList l).get! k' = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := by + simp_to_raw using Raw₀.get!_insertMany_empty_list_of_mem + +theorem getD_ofList_of_contains_eq_false [LawfulBEq α] + {l : List ((a : α) × β a)} {k : α} {fallback : β k} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (ofList l).getD k fallback = fallback := by + simp_to_raw using Raw₀.getD_insertMany_empty_list_of_contains_eq_false + +theorem getD_ofList_of_mem [LawfulBEq α] + {l : List ((a : α) × β a)} {k k' : α} (k_beq : k == k') {v : β k} {fallback : β k'} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (ofList l).getD k' fallback = cast (by congr; apply LawfulBEq.eq_of_beq k_beq) v := by + simp_to_raw using Raw₀.getD_insertMany_empty_list_of_mem + +theorem getKey?_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (ofList l).getKey? k = none := by + simp_to_raw using Raw₀.getKey?_insertMany_empty_list_of_contains_eq_false + +theorem getKey?_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (ofList l).getKey? k' = some k := by + simp_to_raw using Raw₀.getKey?_insertMany_empty_list_of_mem + +theorem getKey_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) + {h'} : + (ofList l).getKey k' h' = k := by + simp_to_raw using Raw₀.getKey_insertMany_empty_list_of_mem + +theorem getKey!_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List ((a : α) × β a)} {k : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (ofList l).getKey! k = default := by + simp_to_raw using Raw₀.getKey!_insertMany_empty_list_of_contains_eq_false + +theorem getKey!_ofList_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List ((a : α) × β a)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (ofList l).getKey! k' = k := by + simp_to_raw using Raw₀.getKey!_insertMany_empty_list_of_mem + +theorem getKeyD_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} {k fallback : α} + (contains_eq_false : (l.map Sigma.fst).contains k = false) : + (ofList l).getKeyD k fallback = fallback := by + simp_to_raw using Raw₀.getKeyD_insertMany_empty_list_of_contains_eq_false + +theorem getKeyD_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Sigma.fst) : + (ofList l).getKeyD k' fallback = k := by + simp_to_raw using Raw₀.getKeyD_insertMany_empty_list_of_mem + +theorem size_ofList [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (ofList l).size = l.length := by + simp_to_raw using Raw₀.size_insertMany_empty_list + +theorem size_ofList_le [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} : + (ofList l).size ≤ l.length := by + simp_to_raw using Raw₀.size_insertMany_empty_list_le + +@[simp] +theorem isEmpty_ofList [EquivBEq α] [LawfulHashable α] + {l : List ((a : α) × β a)} : + (ofList l).isEmpty = l.isEmpty := by + simp_to_raw using Raw₀.isEmpty_insertMany_empty_list + +namespace Const + +variable {β : Type v} + +@[simp] +theorem ofList_nil : + ofList ([] : List (α × β)) = ∅ := by + simp_to_raw + simp + +@[simp] +theorem ofList_singleton {k : α} {v : β} : + ofList [⟨k, v⟩] = (∅ : Raw α (fun _ => β)).insert k v := by + simp_to_raw + simp + +theorem ofList_cons {k : α} {v : β} {tl : List (α × β)} : + ofList (⟨k, v⟩ :: tl) = insertMany ((∅ : Raw α (fun _ => β)).insert k v) tl := by + simp_to_raw + rw [Raw₀.Const.insertMany_empty_list_cons] + +@[simp] +theorem contains_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + (ofList l).contains k = (l.map Prod.fst).contains k := by + simp_to_raw using Raw₀.Const.contains_insertMany_empty_list + +@[simp] +theorem mem_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + k ∈ (ofList l) ↔ (l.map Prod.fst).contains k := by + simp [mem_iff_contains] + +theorem get?_ofList_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + get? (ofList l) k = none := by + simp_to_raw using Raw₀.Const.get?_insertMany_empty_list_of_contains_eq_false + +theorem get?_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + get? (ofList l) k' = some v := by + simp_to_raw using Raw₀.Const.get?_insertMany_empty_list_of_mem + +theorem get_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) + {h} : + get (ofList l) k' h = v := by + simp_to_raw using Raw₀.Const.get_insertMany_empty_list_of_mem + +theorem get!_ofList_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} [Inhabited β] + (contains_eq_false : (l.map Prod.fst).contains k = false) : + get! (ofList l) k = default := by + simp_to_raw using Raw₀.Const.get!_insertMany_empty_list_of_contains_eq_false + +theorem get!_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} [Inhabited β] + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + get! (ofList l) k' = v := by + simp_to_raw using Raw₀.Const.get!_insertMany_empty_list_of_mem + +theorem getD_ofList_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} {fallback : β} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + getD (ofList l) k fallback = fallback := by + simp_to_raw using Raw₀.Const.getD_insertMany_empty_list_of_contains_eq_false + +theorem getD_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} {fallback : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + getD (ofList l) k' fallback = v := by + simp_to_raw using Raw₀.Const.getD_insertMany_empty_list_of_mem + +theorem getKey?_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l).getKey? k = none := by + simp_to_raw using Raw₀.Const.getKey?_insertMany_empty_list_of_contains_eq_false + +theorem getKey?_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (ofList l).getKey? k' = some k := by + simp_to_raw using Raw₀.Const.getKey?_insertMany_empty_list_of_mem + +theorem getKey_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) + {h'} : + (ofList l).getKey k' h' = k := by + simp_to_raw using Raw₀.Const.getKey_insertMany_empty_list_of_mem + +theorem getKey!_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l).getKey! k = default := by + simp_to_raw using Raw₀.Const.getKey!_insertMany_empty_list_of_contains_eq_false + +theorem getKey!_ofList_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (ofList l).getKey! k' = k := by + simp_to_raw using Raw₀.Const.getKey!_insertMany_empty_list_of_mem + +theorem getKeyD_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k fallback : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l).getKeyD k fallback = fallback := by + simp_to_raw using Raw₀.Const.getKeyD_insertMany_empty_list_of_contains_eq_false + +theorem getKeyD_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (ofList l).getKeyD k' fallback = k := by + simp_to_raw using Raw₀.Const.getKeyD_insertMany_empty_list_of_mem + +theorem size_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (ofList l).size = l.length := by + simp_to_raw using Raw₀.Const.size_insertMany_empty_list + +theorem size_ofList_le [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (ofList l).size ≤ l.length := by + simp_to_raw using Raw₀.Const.size_insertMany_empty_list_le + +@[simp] +theorem isEmpty_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (ofList l).isEmpty = l.isEmpty := by + simp_to_raw using Raw₀.Const.isEmpty_insertMany_empty_list + +@[simp] +theorem unitOfList_nil : + unitOfList ([] : List α) = ∅ := by + simp_to_raw + simp + +@[simp] +theorem unitOfList_singleton {k : α} : + unitOfList [k] = (∅ : Raw α (fun _ => Unit)).insertIfNew k () := by + simp_to_raw + simp + +theorem unitOfList_cons {hd : α} {tl : List α} : + unitOfList (hd :: tl) = insertManyIfNewUnit ((∅ : Raw α (fun _ => Unit)).insertIfNew hd ()) tl := by + simp_to_raw + rw [Raw₀.Const.insertManyIfNewUnit_empty_list_cons] + +@[simp] +theorem contains_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (unitOfList l).contains k = l.contains k := by + simp_to_raw using Raw₀.Const.contains_insertManyIfNewUnit_empty_list + +@[simp] +theorem mem_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + k ∈ unitOfList l ↔ l.contains k := by + simp [mem_iff_contains] + +theorem getKey?_unitOfList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (contains_eq_false : l.contains k = false) : + getKey? (unitOfList l) k = none := by + simp_to_raw using Raw₀.Const.getKey?_insertManyIfNewUnit_empty_list_of_contains_eq_false + +theorem getKey?_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getKey? (unitOfList l) k' = some k := by + simp_to_raw using Raw₀.Const.getKey?_insertManyIfNewUnit_empty_list_of_mem + +theorem getKey_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) {h'} : + getKey (unitOfList l) k' h' = k := by + simp_to_raw using Raw₀.Const.getKey_insertManyIfNewUnit_empty_list_of_mem + +theorem getKey!_unitOfList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k : α} + (contains_eq_false : l.contains k = false) : + getKey! (unitOfList l) k = default := by + simp_to_raw using Raw₀.Const.getKey!_insertManyIfNewUnit_empty_list_of_contains_eq_false + +theorem getKey!_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + getKey! (unitOfList l) k' = k := by + simp_to_raw using Raw₀.Const.getKey!_insertManyIfNewUnit_empty_list_of_mem + +theorem getKeyD_unitOfList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k fallback : α} + (contains_eq_false : l.contains k = false) : + getKeyD (unitOfList l) k fallback = fallback := by + simp_to_raw using Raw₀.Const.getKeyD_insertManyIfNewUnit_empty_list_of_contains_eq_false + +theorem getKeyD_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l ) : + getKeyD (unitOfList l) k' fallback = k := by + simp_to_raw using Raw₀.Const.getKeyD_insertManyIfNewUnit_empty_list_of_mem + +theorem size_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (unitOfList l).size = l.length := by + simp_to_raw using Raw₀.Const.size_insertManyIfNewUnit_empty_list + +theorem size_unitOfList_le [EquivBEq α] [LawfulHashable α] + {l : List α} : + (unitOfList l).size ≤ l.length := by + simp_to_raw using Raw₀.Const.size_insertManyIfNewUnit_empty_list_le + +@[simp] +theorem isEmpty_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} : + (unitOfList l).isEmpty = l.isEmpty := by + simp_to_raw using Raw₀.Const.isEmpty_insertManyIfNewUnit_empty_list + +@[simp] +theorem get?_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + get? (unitOfList l) k = + if l.contains k then some () else none := by + simp_to_raw using Raw₀.Const.get?_insertManyIfNewUnit_empty_list + +@[simp] +theorem get_unitOfList + {l : List α} {k : α} {h} : + get (unitOfList l) k h = () := by + simp + +@[simp] +theorem get!_unitOfList + {l : List α} {k : α} : + get! (unitOfList l) k = () := by + simp + +@[simp] +theorem getD_unitOfList + {l : List α} {k : α} {fallback : Unit} : + getD (unitOfList l) k fallback = () := by + simp + +end Const end Raw end Std.DHashMap diff --git a/src/Std/Data/HashMap/Basic.lean b/src/Std/Data/HashMap/Basic.lean index 70e3d0ee5ec9..4602085fb602 100644 --- a/src/Std/Data/HashMap/Basic.lean +++ b/src/Std/Data/HashMap/Basic.lean @@ -191,6 +191,14 @@ instance [BEq α] [Hashable α] : GetElem? (HashMap α β) α β (fun m a => a @[inline, inherit_doc DHashMap.keys] def keys (m : HashMap α β) : List α := m.inner.keys +@[inline, inherit_doc DHashMap.Const.ofList] def ofList [BEq α] [Hashable α] (l : List (α × β)) : + HashMap α β := + ⟨DHashMap.Const.ofList l⟩ + +@[inline, inherit_doc DHashMap.Const.unitOfList] def unitOfList [BEq α] [Hashable α] (l : List α) : + HashMap α Unit := + ⟨DHashMap.Const.unitOfList l⟩ + section Unverified /-! We currently do not provide lemmas for the functions below. -/ @@ -261,20 +269,12 @@ instance [BEq α] [Hashable α] {m : Type w → Type w} : ForIn m (HashMap α β {ρ : Type w} [ForIn Id ρ α] (m : HashMap α Unit) (l : ρ) : HashMap α Unit := ⟨DHashMap.Const.insertManyIfNewUnit m.inner l⟩ -@[inline, inherit_doc DHashMap.Const.ofList] def ofList [BEq α] [Hashable α] (l : List (α × β)) : - HashMap α β := - ⟨DHashMap.Const.ofList l⟩ - /-- Computes the union of the given hash maps, by traversing `m₂` and inserting its elements into `m₁`. -/ @[inline] def union [BEq α] [Hashable α] (m₁ m₂ : HashMap α β) : HashMap α β := m₂.fold (init := m₁) fun acc x => acc.insert x instance [BEq α] [Hashable α] : Union (HashMap α β) := ⟨union⟩ -@[inline, inherit_doc DHashMap.Const.unitOfList] def unitOfList [BEq α] [Hashable α] (l : List α) : - HashMap α Unit := - ⟨DHashMap.Const.unitOfList l⟩ - @[inline, inherit_doc DHashMap.Const.unitOfArray] def unitOfArray [BEq α] [Hashable α] (l : Array α) : HashMap α Unit := ⟨DHashMap.Const.unitOfArray l⟩ diff --git a/src/Std/Data/HashMap/Lemmas.lean b/src/Std/Data/HashMap/Lemmas.lean index 5e9f89e692fa..688be7b35a72 100644 --- a/src/Std/Data/HashMap/Lemmas.lean +++ b/src/Std/Data/HashMap/Lemmas.lean @@ -698,6 +698,575 @@ theorem distinct_keys [EquivBEq α] [LawfulHashable α] : m.keys.Pairwise (fun a b => (a == b) = false) := DHashMap.distinct_keys +@[simp] +theorem insertMany_nil : + insertMany m [] = m := + ext DHashMap.Const.insertMany_nil + +@[simp] +theorem insertMany_list_singleton {k : α} {v : β} : + insertMany m [⟨k, v⟩] = m.insert k v := + ext DHashMap.Const.insertMany_list_singleton + +theorem insertMany_cons {l : List (α × β)} {k : α} {v : β} : + insertMany m (⟨k, v⟩ :: l) = insertMany (m.insert k v) l := + ext DHashMap.Const.insertMany_cons + +@[simp] +theorem contains_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + (insertMany m l).contains k = (m.contains k || (l.map Prod.fst).contains k) := + DHashMap.Const.contains_insertMany_list + +@[simp] +theorem mem_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + k ∈ insertMany m l ↔ k ∈ m ∨ (l.map Prod.fst).contains k := + DHashMap.Const.mem_insertMany_list + +theorem mem_of_mem_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} (mem : k ∈ insertMany m l) + (contains_eq_false : (l.map Prod.fst).contains k = false) : + k ∈ m := + DHashMap.Const.mem_of_mem_insertMany_list mem contains_eq_false + +theorem getElem?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l)[k]? = m[k]? := + DHashMap.Const.get?_insertMany_list_of_contains_eq_false contains_eq_false + +theorem getElem?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + (insertMany m l)[k']? = some v := + DHashMap.Const.get?_insertMany_list_of_mem k_beq distinct mem + +theorem getElem_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) + {h} : + (insertMany m l)[k] = m[k]'(mem_of_mem_insertMany_list h contains_eq_false) := + DHashMap.Const.get_insertMany_list_of_contains_eq_false contains_eq_false + +theorem getElem_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) {h} : + (insertMany m l)[k'] = v := + DHashMap.Const.get_insertMany_list_of_mem k_beq distinct mem + +theorem getElem!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited β] {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l)[k]! = m[k]! := + DHashMap.Const.get!_insertMany_list_of_contains_eq_false contains_eq_false + +theorem getElem!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited β] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + (insertMany m l)[k']! = v := + DHashMap.Const.get!_insertMany_list_of_mem k_beq distinct mem + +theorem getD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} {fallback : β} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + getD (insertMany m l) k fallback = getD m k fallback := + DHashMap.Const.getD_insertMany_list_of_contains_eq_false contains_eq_false + +theorem getD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v fallback : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + getD (insertMany m l) k' fallback = v := + DHashMap.Const.getD_insertMany_list_of_mem k_beq distinct mem + +theorem getKey?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l).getKey? k = m.getKey? k := + DHashMap.Const.getKey?_insertMany_list_of_contains_eq_false contains_eq_false + +theorem getKey?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).getKey? k' = some k := + DHashMap.Const.getKey?_insertMany_list_of_mem k_beq distinct mem + +theorem getKey_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) + {h} : + (insertMany m l).getKey k h = + m.getKey k (mem_of_mem_insertMany_list h contains_eq_false) := + DHashMap.Const.getKey_insertMany_list_of_contains_eq_false contains_eq_false + +theorem getKey_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) + {h} : + (insertMany m l).getKey k' h = k := + DHashMap.Const.getKey_insertMany_list_of_mem k_beq distinct mem + +theorem getKey!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l).getKey! k = m.getKey! k := + DHashMap.Const.getKey!_insertMany_list_of_contains_eq_false contains_eq_false + +theorem getKey!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).getKey! k' = k := + DHashMap.Const.getKey!_insertMany_list_of_mem k_beq distinct mem + +theorem getKeyD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k fallback : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l).getKeyD k fallback = m.getKeyD k fallback := + DHashMap.Const.getKeyD_insertMany_list_of_contains_eq_false contains_eq_false + +theorem getKeyD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).getKeyD k' fallback = k := + DHashMap.Const.getKeyD_insertMany_list_of_mem k_beq distinct mem + +theorem size_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (∀ (a : α), a ∈ m → (l.map Prod.fst).contains a = false) → + (insertMany m l).size = m.size + l.length := + DHashMap.Const.size_insertMany_list distinct + +theorem size_le_size_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + m.size ≤ (insertMany m l).size := + DHashMap.Const.size_le_size_insertMany_list + +theorem size_insertMany_list_le [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (insertMany m l).size ≤ m.size + l.length := + DHashMap.Const.size_insertMany_list_le + +@[simp] +theorem isEmpty_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (insertMany m l).isEmpty = (m.isEmpty && l.isEmpty) := + DHashMap.Const.isEmpty_insertMany_list + +variable {m : HashMap α Unit} + +@[simp] +theorem insertManyIfNewUnit_nil : + insertManyIfNewUnit m [] = m := + ext DHashMap.Const.insertManyIfNewUnit_nil + +@[simp] +theorem insertManyIfNewUnit_list_singleton {k : α} : + insertManyIfNewUnit m [k] = m.insertIfNew k () := + ext DHashMap.Const.insertManyIfNewUnit_list_singleton + +theorem insertManyIfNewUnit_cons {l : List α} {k : α} : + insertManyIfNewUnit m (k :: l) = insertManyIfNewUnit (m.insertIfNew k ()) l := + ext DHashMap.Const.insertManyIfNewUnit_cons + +@[simp] +theorem contains_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (insertManyIfNewUnit m l).contains k = (m.contains k || l.contains k) := + DHashMap.Const.contains_insertManyIfNewUnit_list + +@[simp] +theorem mem_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + k ∈ insertManyIfNewUnit m l ↔ k ∈ m ∨ l.contains k := + DHashMap.Const.mem_insertManyIfNewUnit_list + +theorem mem_of_mem_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (contains_eq_false : l.contains k = false) : + k ∈ insertManyIfNewUnit m l → k ∈ m := + DHashMap.Const.mem_of_mem_insertManyIfNewUnit_list contains_eq_false + +theorem getElem?_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (insertManyIfNewUnit m l)[k]? = + if k ∈ m ∨ l.contains k then some () else none := + DHashMap.Const.get?_insertManyIfNewUnit_list + +theorem getElem_insertManyIfNewUnit_list + {l : List α} {k : α} {h} : + (insertManyIfNewUnit m l)[k] = () := + DHashMap.Const.get_insertManyIfNewUnit_list + +theorem getElem!_insertManyIfNewUnit_list + {l : List α} {k : α} : + (insertManyIfNewUnit m l)[k]! = () := + DHashMap.Const.get!_insertManyIfNewUnit_list + +theorem getD_insertManyIfNewUnit_list + {l : List α} {k : α} {fallback : Unit} : + getD (insertManyIfNewUnit m l) k fallback = () := by + simp + +theorem getKey?_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] {l : List α} {k : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + getKey? (insertManyIfNewUnit m l) k = none := + DHashMap.Const.getKey?_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + not_mem contains_eq_false + +theorem getKey?_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' : α} (k_beq : k == k') (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getKey? (insertManyIfNewUnit m l) k' = some k := + DHashMap.Const.getKey?_insertManyIfNewUnit_list_of_not_mem_of_mem + k_beq not_mem distinct mem + +theorem getKey?_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (mem : k ∈ m) : + getKey? (insertManyIfNewUnit m l) k = getKey? m k := + DHashMap.Const.getKey?_insertManyIfNewUnit_list_of_mem mem + +theorem getKey_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' : α} (k_beq : k == k') (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) {h} : + getKey (insertManyIfNewUnit m l) k' h = k := + DHashMap.Const.getKey_insertManyIfNewUnit_list_of_not_mem_of_mem + k_beq not_mem distinct mem + +theorem getKey_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (mem : k ∈ m) {h} : + getKey (insertManyIfNewUnit m l) k h = getKey m k mem := + DHashMap.Const.getKey_insertManyIfNewUnit_list_of_mem mem + +theorem getKey!_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] [Inhabited α] {l : List α} {k : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + getKey! (insertManyIfNewUnit m l) k = default := + DHashMap.Const.getKey!_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + not_mem contains_eq_false + +theorem getKey!_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getKey! (insertManyIfNewUnit m l) k' = k := + DHashMap.Const.getKey!_insertManyIfNewUnit_list_of_not_mem_of_mem + k_beq not_mem distinct mem + +theorem getKey!_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k : α} (mem : k ∈ m) : + getKey! (insertManyIfNewUnit m l) k = getKey! m k := + DHashMap.Const.getKey!_insertManyIfNewUnit_list_of_mem mem + +theorem getKeyD_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] {l : List α} {k fallback : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + getKeyD (insertManyIfNewUnit m l) k fallback = fallback := + DHashMap.Const.getKeyD_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + not_mem contains_eq_false + +theorem getKeyD_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' fallback : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l ) : + getKeyD (insertManyIfNewUnit m l) k' fallback = k := + DHashMap.Const.getKeyD_insertManyIfNewUnit_list_of_not_mem_of_mem + k_beq not_mem distinct mem + +theorem getKeyD_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k fallback : α} (mem : k ∈ m) : + getKeyD (insertManyIfNewUnit m l) k fallback = getKeyD m k fallback := + DHashMap.Const.getKeyD_insertManyIfNewUnit_list_of_mem mem + +theorem size_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (∀ (a : α), a ∈ m → l.contains a = false) → + (insertManyIfNewUnit m l).size = m.size + l.length := + DHashMap.Const.size_insertManyIfNewUnit_list distinct + +theorem size_le_size_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} : + m.size ≤ (insertManyIfNewUnit m l).size := + DHashMap.Const.size_le_size_insertManyIfNewUnit_list + +theorem size_insertManyIfNewUnit_list_le [EquivBEq α] [LawfulHashable α] + {l : List α} : + (insertManyIfNewUnit m l).size ≤ m.size + l.length := + DHashMap.Const.size_insertManyIfNewUnit_list_le + +@[simp] +theorem isEmpty_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] + {l : List α} : + (insertManyIfNewUnit m l).isEmpty = (m.isEmpty && l.isEmpty) := + DHashMap.Const.isEmpty_insertManyIfNewUnit_list + +end + +section + +@[simp] +theorem ofList_nil : + ofList ([] : List (α × β)) = ∅ := + ext DHashMap.Const.ofList_nil + +@[simp] +theorem ofList_singleton {k : α} {v : β} : + ofList [⟨k, v⟩] = (∅ : HashMap α β).insert k v := + ext DHashMap.Const.ofList_singleton + +theorem ofList_cons {k : α} {v : β} {tl : List (α × β)} : + ofList (⟨k, v⟩ :: tl) = insertMany ((∅ : HashMap α β).insert k v) tl := + ext DHashMap.Const.ofList_cons + +@[simp] +theorem contains_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + (ofList l).contains k = (l.map Prod.fst).contains k := + DHashMap.Const.contains_ofList + +@[simp] +theorem mem_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + k ∈ ofList l ↔ (l.map Prod.fst).contains k := + DHashMap.Const.mem_ofList + +theorem getElem?_ofList_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l)[k]? = none := + DHashMap.Const.get?_ofList_of_contains_eq_false contains_eq_false + +theorem getElem?_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (ofList l)[k']? = some v := + DHashMap.Const.get?_ofList_of_mem k_beq distinct mem + +theorem getElem_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) + {h} : + (ofList l)[k'] = v := + DHashMap.Const.get_ofList_of_mem k_beq distinct mem + +theorem getElem!_ofList_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} [Inhabited β] + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l)[k]! = (default : β) := + DHashMap.Const.get!_ofList_of_contains_eq_false contains_eq_false + +theorem getElem!_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} [Inhabited β] + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (ofList l)[k']! = v := + DHashMap.Const.get!_ofList_of_mem k_beq distinct mem + +theorem getD_ofList_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} {fallback : β} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + getD (ofList l) k fallback = fallback := + DHashMap.Const.getD_ofList_of_contains_eq_false contains_eq_false + +theorem getD_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} {fallback : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + getD (ofList l) k' fallback = v := + DHashMap.Const.getD_ofList_of_mem k_beq distinct mem + +theorem getKey?_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l).getKey? k = none := + DHashMap.Const.getKey?_ofList_of_contains_eq_false contains_eq_false + +theorem getKey?_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (ofList l).getKey? k' = some k := + DHashMap.Const.getKey?_ofList_of_mem k_beq distinct mem + +theorem getKey_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) + {h} : + (ofList l).getKey k' h = k := + DHashMap.Const.getKey_ofList_of_mem k_beq distinct mem + +theorem getKey!_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l).getKey! k = default := + DHashMap.Const.getKey!_ofList_of_contains_eq_false contains_eq_false + +theorem getKey!_ofList_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (ofList l).getKey! k' = k := + DHashMap.Const.getKey!_ofList_of_mem k_beq distinct mem + +theorem getKeyD_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k fallback : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l).getKeyD k fallback = fallback := + DHashMap.Const.getKeyD_ofList_of_contains_eq_false contains_eq_false + +theorem getKeyD_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (ofList l).getKeyD k' fallback = k := + DHashMap.Const.getKeyD_ofList_of_mem k_beq distinct mem + +theorem size_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (ofList l).size = l.length := + DHashMap.Const.size_ofList distinct + +theorem size_ofList_le [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (ofList l).size ≤ l.length := + DHashMap.Const.size_ofList_le + +@[simp] +theorem isEmpty_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (ofList l).isEmpty = l.isEmpty := + DHashMap.Const.isEmpty_ofList + +@[simp] +theorem unitOfList_nil : + unitOfList ([] : List α) = ∅ := + ext DHashMap.Const.unitOfList_nil + +@[simp] +theorem unitOfList_singleton {k : α} : + unitOfList [k] = (∅ : HashMap α Unit).insertIfNew k () := + ext DHashMap.Const.unitOfList_singleton + +theorem unitOfList_cons {hd : α} {tl : List α} : + unitOfList (hd :: tl) = + insertManyIfNewUnit ((∅ : HashMap α Unit).insertIfNew hd ()) tl := + ext DHashMap.Const.unitOfList_cons + +@[simp] +theorem contains_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (unitOfList l).contains k = l.contains k := + DHashMap.Const.contains_unitOfList + +@[simp] +theorem mem_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + k ∈ unitOfList l ↔ l.contains k := + DHashMap.Const.mem_unitOfList + +@[simp] +theorem getElem?_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (unitOfList l)[k]? = + if l.contains k then some () else none := + DHashMap.Const.get?_unitOfList + +@[simp] +theorem getElem_unitOfList + {l : List α} {k : α} {h} : + (unitOfList l)[k] = () := + DHashMap.Const.get_unitOfList + +@[simp] +theorem getElem!_unitOfList + {l : List α} {k : α} : + (unitOfList l)[k]! = () := + DHashMap.Const.get!_unitOfList + +@[simp] +theorem getD_unitOfList + {l : List α} {k : α} {fallback : Unit} : + getD (unitOfList l) k fallback = () := by + simp + +theorem getKey?_unitOfList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (contains_eq_false : l.contains k = false) : + getKey? (unitOfList l) k = none := + DHashMap.Const.getKey?_unitOfList_of_contains_eq_false contains_eq_false + +theorem getKey?_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getKey? (unitOfList l) k' = some k := + DHashMap.Const.getKey?_unitOfList_of_mem k_beq distinct mem + +theorem getKey_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) {h} : + getKey (unitOfList l) k' h = k := + DHashMap.Const.getKey_unitOfList_of_mem k_beq distinct mem + +theorem getKey!_unitOfList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k : α} + (contains_eq_false : l.contains k = false) : + getKey! (unitOfList l) k = default := + DHashMap.Const.getKey!_unitOfList_of_contains_eq_false contains_eq_false + +theorem getKey!_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + getKey! (unitOfList l) k' = k := + DHashMap.Const.getKey!_unitOfList_of_mem k_beq distinct mem + +theorem getKeyD_unitOfList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k fallback : α} + (contains_eq_false : l.contains k = false) : + getKeyD (unitOfList l) k fallback = fallback := + DHashMap.Const.getKeyD_unitOfList_of_contains_eq_false contains_eq_false + +theorem getKeyD_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + getKeyD (unitOfList l) k' fallback = k := + DHashMap.Const.getKeyD_unitOfList_of_mem k_beq distinct mem + +theorem size_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (unitOfList l).size = l.length := + DHashMap.Const.size_unitOfList distinct + +theorem size_unitOfList_le [EquivBEq α] [LawfulHashable α] + {l : List α} : + (unitOfList l).size ≤ l.length := + DHashMap.Const.size_unitOfList_le + +@[simp] +theorem isEmpty_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} : + (unitOfList l).isEmpty = l.isEmpty := + DHashMap.Const.isEmpty_unitOfList + end end Std.HashMap diff --git a/src/Std/Data/HashMap/Raw.lean b/src/Std/Data/HashMap/Raw.lean index 91718cb8f368..5db2a768e678 100644 --- a/src/Std/Data/HashMap/Raw.lean +++ b/src/Std/Data/HashMap/Raw.lean @@ -173,6 +173,14 @@ instance [BEq α] [Hashable α] : GetElem? (Raw α β) α β (fun m a => a ∈ m @[inline, inherit_doc DHashMap.Raw.keys] def keys (m : Raw α β) : List α := m.inner.keys +@[inline, inherit_doc DHashMap.Raw.Const.ofList] def ofList [BEq α] [Hashable α] + (l : List (α × β)) : Raw α β := + ⟨DHashMap.Raw.Const.ofList l⟩ + +@[inline, inherit_doc DHashMap.Raw.Const.unitOfList] def unitOfList [BEq α] [Hashable α] + (l : List α) : Raw α Unit := + ⟨DHashMap.Raw.Const.unitOfList l⟩ + section Unverified /-! We currently do not provide lemmas for the functions below. -/ @@ -233,20 +241,12 @@ m.inner.values [Hashable α] {ρ : Type w} [ForIn Id ρ α] (m : Raw α Unit) (l : ρ) : Raw α Unit := ⟨DHashMap.Raw.Const.insertManyIfNewUnit m.inner l⟩ -@[inline, inherit_doc DHashMap.Raw.Const.ofList] def ofList [BEq α] [Hashable α] - (l : List (α × β)) : Raw α β := - ⟨DHashMap.Raw.Const.ofList l⟩ - /-- Computes the union of the given hash maps, by traversing `m₂` and inserting its elements into `m₁`. -/ @[inline] def union [BEq α] [Hashable α] (m₁ m₂ : Raw α β) : Raw α β := m₂.fold (init := m₁) fun acc x => acc.insert x instance [BEq α] [Hashable α] : Union (Raw α β) := ⟨union⟩ -@[inline, inherit_doc DHashMap.Raw.Const.unitOfList] def unitOfList [BEq α] [Hashable α] - (l : List α) : Raw α Unit := - ⟨DHashMap.Raw.Const.unitOfList l⟩ - @[inline, inherit_doc DHashMap.Raw.Const.unitOfArray] def unitOfArray [BEq α] [Hashable α] (l : Array α) : Raw α Unit := ⟨DHashMap.Raw.Const.unitOfArray l⟩ diff --git a/src/Std/Data/HashMap/RawLemmas.lean b/src/Std/Data/HashMap/RawLemmas.lean index cc0816a966c7..02d8442c622c 100644 --- a/src/Std/Data/HashMap/RawLemmas.lean +++ b/src/Std/Data/HashMap/RawLemmas.lean @@ -671,7 +671,6 @@ theorem getKeyD_insertIfNew [EquivBEq α] [LawfulHashable α] (h : m.WF) {k a fa (m.insertIfNew k v).getKeyD a fallback = if k == a ∧ ¬k ∈ m then k else m.getKeyD a fallback := DHashMap.Raw.getKeyD_insertIfNew h.out - @[simp] theorem getThenInsertIfNew?_fst (h : m.WF) {k : α} {v : β} : (getThenInsertIfNew? m k v).1 = get? m k := @@ -688,7 +687,7 @@ theorem length_keys [EquivBEq α] [LawfulHashable α] (h : m.WF) : DHashMap.Raw.length_keys h.out @[simp] -theorem isEmpty_keys [EquivBEq α] [LawfulHashable α] (h : m.WF): +theorem isEmpty_keys [EquivBEq α] [LawfulHashable α] (h : m.WF) : m.keys.isEmpty = m.isEmpty := DHashMap.Raw.isEmpty_keys h.out @@ -699,13 +698,592 @@ theorem contains_keys [EquivBEq α] [LawfulHashable α] (h : m.WF) {k : α} : @[simp] theorem mem_keys [LawfulBEq α] [LawfulHashable α] (h : m.WF) {k : α} : - k ∈ m.keys ↔ k ∈ m := + k ∈ m.keys ↔ k ∈ m := DHashMap.Raw.mem_keys h.out theorem distinct_keys [EquivBEq α] [LawfulHashable α] (h : m.WF) : - m.keys.Pairwise (fun a b => (a == b) = false) := + m.keys.Pairwise (fun a b => (a == b) = false) := DHashMap.Raw.distinct_keys h.out +@[simp] +theorem insertMany_nil (h : m.WF) : + insertMany m [] = m := + ext (DHashMap.Raw.Const.insertMany_nil h.out) + +@[simp] +theorem insertMany_list_singleton (h : m.WF) + {k : α} {v : β} : + insertMany m [⟨k, v⟩] = m.insert k v := + ext (DHashMap.Raw.Const.insertMany_list_singleton h.out) + +theorem insertMany_cons (h : m.WF) {l : List (α × β)} + {k : α} {v : β} : + insertMany m (⟨k, v⟩ :: l) = insertMany (m.insert k v) l := + ext (DHashMap.Raw.Const.insertMany_cons h.out) + +@[simp] +theorem contains_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k : α} : + (insertMany m l).contains k = (m.contains k || (l.map Prod.fst).contains k) := + DHashMap.Raw.Const.contains_insertMany_list h.out + +@[simp] +theorem mem_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k : α} : + k ∈ insertMany m l ↔ k ∈ m ∨ (l.map Prod.fst).contains k := + DHashMap.Raw.Const.mem_insertMany_list h.out + +theorem mem_of_mem_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List (α × β)} {k : α} : + k ∈ insertMany m l → (l.map Prod.fst).contains k = false → k ∈ m := + DHashMap.Raw.Const.mem_of_mem_insertMany_list h.out + +theorem getKey?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l).getKey? k = m.getKey? k := + DHashMap.Raw.Const.getKey?_insertMany_list_of_contains_eq_false h.out contains_eq_false + +theorem getKey?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).getKey? k' = some k := + DHashMap.Raw.Const.getKey?_insertMany_list_of_mem h.out k_beq distinct mem + +theorem getKey_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) + {h'} : + (insertMany m l).getKey k h' = + m.getKey k (mem_of_mem_insertMany_list h h' contains_eq_false) := + DHashMap.Raw.Const.getKey_insertMany_list_of_contains_eq_false h.out contains_eq_false + +theorem getKey_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) + {h'} : + (insertMany m l).getKey k' h' = k := + DHashMap.Raw.Const.getKey_insertMany_list_of_mem h.out k_beq distinct mem + +theorem getKey!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] [Inhabited α] + (h : m.WF) {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l).getKey! k = m.getKey! k := + DHashMap.Raw.Const.getKey!_insertMany_list_of_contains_eq_false h.out contains_eq_false + +theorem getKey!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] + (h : m.WF) {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).getKey! k' = k := + DHashMap.Raw.Const.getKey!_insertMany_list_of_mem h.out k_beq distinct mem + +theorem getKeyD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} {k fallback : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l).getKeyD k fallback = m.getKeyD k fallback := + DHashMap.Raw.Const.getKeyD_insertMany_list_of_contains_eq_false h.out contains_eq_false + +theorem getKeyD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (insertMany m l).getKeyD k' fallback = k := + DHashMap.Raw.Const.getKeyD_insertMany_list_of_mem h.out k_beq distinct mem + +theorem size_insertMany_list [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (∀ (a : α), a ∈ m → (l.map Prod.fst).contains a = false) → + (insertMany m l).size = m.size + l.length := + DHashMap.Raw.Const.size_insertMany_list h.out distinct + +theorem size_le_size_insertMany_list [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} : + m.size ≤ (insertMany m l).size := + DHashMap.Raw.Const.size_le_size_insertMany_list h.out + +theorem size_insertMany_list_le [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} : + (insertMany m l).size ≤ m.size + l.length := + DHashMap.Raw.Const.size_insertMany_list_le h.out + +@[simp] +theorem isEmpty_insertMany_list [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} : + (insertMany m l).isEmpty = (m.isEmpty && l.isEmpty) := + DHashMap.Raw.Const.isEmpty_insertMany_list h.out + +theorem getElem?_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l)[k]? = m[k]? := + DHashMap.Raw.Const.get?_insertMany_list_of_contains_eq_false h.out contains_eq_false + +theorem getElem?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + (insertMany m l)[k']? = v := + DHashMap.Raw.Const.get?_insertMany_list_of_mem h.out k_beq distinct mem + +theorem getElem_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) + {h'} : + (insertMany m l)[k] = + m[k]'(mem_of_mem_insertMany_list h h' contains_eq_false) := + DHashMap.Raw.Const.get_insertMany_list_of_contains_eq_false h.out contains_eq_false (h':= h') + +theorem getElem_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) {h'} : + (insertMany m l)[k'] = v := + DHashMap.Raw.Const.get_insertMany_list_of_mem h.out k_beq distinct mem (h' := h') + +theorem getElem!_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited β] (h : m.WF) {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (insertMany m l)[k]! = m[k]! := + DHashMap.Raw.Const.get!_insertMany_list_of_contains_eq_false h.out contains_eq_false + +theorem getElem!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited β] + (h : m.WF) {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + (insertMany m l)[k']! = v := + DHashMap.Raw.Const.get!_insertMany_list_of_mem h.out k_beq distinct mem + +theorem getD_insertMany_list_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} {k : α} {fallback : β} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + getD (insertMany m l) k fallback = getD m k fallback := + DHashMap.Raw.Const.getD_insertMany_list_of_contains_eq_false h.out contains_eq_false + +theorem getD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List (α × β)} {k k' : α} (k_beq : k == k') {v fallback : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) (mem : ⟨k, v⟩ ∈ l) : + getD (insertMany m l) k' fallback = v := + DHashMap.Raw.Const.getD_insertMany_list_of_mem h.out k_beq distinct mem + +variable {m : Raw α Unit} + +@[simp] +theorem insertManyIfNewUnit_nil (h : m.WF) : + insertManyIfNewUnit m [] = m := + ext (DHashMap.Raw.Const.insertManyIfNewUnit_nil h.out) + +@[simp] +theorem insertManyIfNewUnit_list_singleton (h : m.WF) {k : α} : + insertManyIfNewUnit m [k] = m.insertIfNew k () := + ext (DHashMap.Raw.Const.insertManyIfNewUnit_list_singleton h.out) + +theorem insertManyIfNewUnit_cons (h : m.WF) {l : List α} {k : α} : + insertManyIfNewUnit m (k :: l) = insertManyIfNewUnit (m.insertIfNew k ()) l := + ext (DHashMap.Raw.Const.insertManyIfNewUnit_cons h.out) + +@[simp] +theorem contains_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} {k : α} : + (insertManyIfNewUnit m l).contains k = (m.contains k || l.contains k) := + DHashMap.Raw.Const.contains_insertManyIfNewUnit_list h.out + +@[simp] +theorem mem_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} {k : α} : + k ∈ insertManyIfNewUnit m l ↔ k ∈ m ∨ l.contains k := + DHashMap.Raw.Const.mem_insertManyIfNewUnit_list h.out + +theorem mem_of_mem_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} {k : α} (contains_eq_false : l.contains k = false) : + k ∈ insertManyIfNewUnit m l → k ∈ m := + DHashMap.Raw.Const.mem_of_mem_insertManyIfNewUnit_list h.out contains_eq_false + +theorem getKey?_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] (h : m.WF) {l : List α} {k : α} + (not_mem : ¬ k ∈ m) (contains_eq_false: l.contains k = false) : + getKey? (insertManyIfNewUnit m l) k = none := + DHashMap.Raw.Const.getKey?_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + h.out not_mem contains_eq_false + +theorem getKey?_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getKey? (insertManyIfNewUnit m l) k' = some k := + DHashMap.Raw.Const.getKey?_insertManyIfNewUnit_list_of_not_mem_of_mem + h.out k_beq not_mem distinct mem + +theorem getKey?_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k : α} (mem : k ∈ m) : + getKey? (insertManyIfNewUnit m l) k = getKey? m k := + DHashMap.Raw.Const.getKey?_insertManyIfNewUnit_list_of_mem h.out mem + +theorem getKey_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} + {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) {h'} : + getKey (insertManyIfNewUnit m l) k' h' = k := + DHashMap.Raw.Const.getKey_insertManyIfNewUnit_list_of_not_mem_of_mem + h.out k_beq not_mem distinct mem + +theorem getKey_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k : α} (mem: k ∈ m) {h₃} : + getKey (insertManyIfNewUnit m l) k h₃ = getKey m k mem := + DHashMap.Raw.Const.getKey_insertManyIfNewUnit_list_of_mem h.out mem + +theorem getKey!_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] [Inhabited α] (h : m.WF) {l : List α} {k : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + getKey! (insertManyIfNewUnit m l) k = default := + DHashMap.Raw.Const.getKey!_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + h.out not_mem contains_eq_false + +theorem getKey!_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] (h : m.WF) {l : List α} {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getKey! (insertManyIfNewUnit m l) k' = k := + DHashMap.Raw.Const.getKey!_insertManyIfNewUnit_list_of_not_mem_of_mem + h.out k_beq not_mem distinct mem + +theorem getKey!_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] (h : m.WF) {l : List α} {k : α} (mem : k ∈ m) : + getKey! (insertManyIfNewUnit m l) k = getKey! m k := + DHashMap.Raw.Const.getKey!_insertManyIfNewUnit_list_of_mem h.out mem + +theorem getKeyD_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] (h : m.WF) {l : List α} {k fallback : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + getKeyD (insertManyIfNewUnit m l) k fallback = fallback := + DHashMap.Raw.Const.getKeyD_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + h.out not_mem contains_eq_false + +theorem getKeyD_insertManyIfNewUnit_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k k' fallback : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getKeyD (insertManyIfNewUnit m l) k' fallback = k := + DHashMap.Raw.Const.getKeyD_insertManyIfNewUnit_list_of_not_mem_of_mem + h.out k_beq not_mem distinct mem + +theorem getKeyD_insertManyIfNewUnit_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k fallback : α} (mem : k ∈ m) : + getKeyD (insertManyIfNewUnit m l) k fallback = getKeyD m k fallback := + DHashMap.Raw.Const.getKeyD_insertManyIfNewUnit_list_of_mem h.out mem + +theorem size_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (∀ (a : α), a ∈ m → l.contains a = false) → + (insertManyIfNewUnit m l).size = m.size + l.length := + DHashMap.Raw.Const.size_insertManyIfNewUnit_list h.out distinct + +theorem size_le_size_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} : + m.size ≤ (insertManyIfNewUnit m l).size := + DHashMap.Raw.Const.size_le_size_insertManyIfNewUnit_list h.out + +theorem size_insertManyIfNewUnit_list_le [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} : + (insertManyIfNewUnit m l).size ≤ m.size + l.length := + DHashMap.Raw.Const.size_insertManyIfNewUnit_list_le h.out + +@[simp] +theorem isEmpty_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} : + (insertManyIfNewUnit m l).isEmpty = (m.isEmpty && l.isEmpty) := + DHashMap.Raw.Const.isEmpty_insertManyIfNewUnit_list h.out + +@[simp] +theorem getElem?_insertManyIfNewUnit_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} {k : α} : + (insertManyIfNewUnit m l)[k]? = + if k ∈ m ∨ l.contains k then some () else none := + DHashMap.Raw.Const.get?_insertManyIfNewUnit_list h.out + +@[simp] +theorem getElem_insertManyIfNewUnit_list + {l : List α} {k : α} {h} : + (insertManyIfNewUnit m l)[k] = () := + DHashMap.Raw.Const.get_insertManyIfNewUnit_list (h:=h) + +@[simp] +theorem getElem!_insertManyIfNewUnit_list + {l : List α} {k : α} : + (insertManyIfNewUnit m l)[k]! = () := + DHashMap.Raw.Const.get!_insertManyIfNewUnit_list + +@[simp] +theorem getD_insertManyIfNewUnit_list + {l : List α} {k : α} {fallback : Unit} : + getD (insertManyIfNewUnit m l) k fallback = () := by + simp + +end Raw + +namespace Raw + +variable [BEq α] [Hashable α] + +@[simp] +theorem ofList_nil : + ofList ([] : List (α × β)) = ∅ := + ext DHashMap.Raw.Const.ofList_nil + +@[simp] +theorem ofList_singleton {k : α} {v : β} : + ofList [⟨k, v⟩] = (∅ : Raw α β).insert k v := + ext DHashMap.Raw.Const.ofList_singleton + +theorem ofList_cons {k : α} {v : β} {tl : List (α × β)} : + ofList (⟨k, v⟩ :: tl) = insertMany ((∅ : Raw α β).insert k v) tl := + ext DHashMap.Raw.Const.ofList_cons + +@[simp] +theorem contains_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + (ofList l).contains k = (l.map Prod.fst).contains k := + DHashMap.Raw.Const.contains_ofList + +@[simp] +theorem mem_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} : + k ∈ (ofList l) ↔ (l.map Prod.fst).contains k := + DHashMap.Raw.Const.mem_ofList + +theorem getElem?_ofList_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l)[k]? = none := + DHashMap.Raw.Const.get?_ofList_of_contains_eq_false contains_eq_false + +theorem getElem?_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (ofList l)[k']? = some v := + DHashMap.Raw.Const.get?_ofList_of_mem k_beq distinct mem + +theorem getElem_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) + {h} : + (ofList l)[k'] = v := + DHashMap.Raw.Const.get_ofList_of_mem k_beq distinct mem (h:=h) + +theorem getElem!_ofList_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} [Inhabited β] + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l)[k]! = default := + DHashMap.Raw.Const.get!_ofList_of_contains_eq_false contains_eq_false + +theorem getElem!_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} [Inhabited β] + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + (ofList l)[k']! = v := + DHashMap.Raw.Const.get!_ofList_of_mem k_beq distinct mem + +theorem getD_ofList_of_contains_eq_false [LawfulBEq α] + {l : List (α × β)} {k : α} {fallback : β} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + getD (ofList l) k fallback = fallback := + DHashMap.Raw.Const.getD_ofList_of_contains_eq_false contains_eq_false + +theorem getD_ofList_of_mem [LawfulBEq α] + {l : List (α × β)} {k k' : α} (k_beq : k == k') {v : β} {fallback : β} + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : ⟨k, v⟩ ∈ l) : + getD (ofList l) k' fallback = v := + DHashMap.Raw.Const.getD_ofList_of_mem k_beq distinct mem + +theorem getKey?_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l).getKey? k = none := + DHashMap.Raw.Const.getKey?_ofList_of_contains_eq_false contains_eq_false + +theorem getKey?_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (ofList l).getKey? k' = some k := + DHashMap.Raw.Const.getKey?_ofList_of_mem k_beq distinct mem + +theorem getKey_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) + {h'} : + (ofList l).getKey k' h' = k := + DHashMap.Raw.Const.getKey_ofList_of_mem k_beq distinct mem + +theorem getKey!_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List (α × β)} {k : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l).getKey! k = default := + DHashMap.Raw.Const.getKey!_ofList_of_contains_eq_false contains_eq_false + +theorem getKey!_ofList_of_mem [EquivBEq α] [LawfulHashable α] [Inhabited α] + {l : List (α × β)} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (ofList l).getKey! k' = k := + DHashMap.Raw.Const.getKey!_ofList_of_mem k_beq distinct mem + +theorem getKeyD_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} {k fallback : α} + (contains_eq_false : (l.map Prod.fst).contains k = false) : + (ofList l).getKeyD k fallback = fallback := + DHashMap.Raw.Const.getKeyD_ofList_of_contains_eq_false contains_eq_false + +theorem getKeyD_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} + {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) + (mem : k ∈ l.map Prod.fst) : + (ofList l).getKeyD k' fallback = k := + DHashMap.Raw.Const.getKeyD_ofList_of_mem k_beq distinct mem + +theorem size_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} (distinct : l.Pairwise (fun a b => (a.1 == b.1) = false)) : + (ofList l).size = l.length := + DHashMap.Raw.Const.size_ofList distinct + +theorem size_ofList_le [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (ofList l).size ≤ l.length := + DHashMap.Raw.Const.size_ofList_le + +@[simp] +theorem isEmpty_ofList [EquivBEq α] [LawfulHashable α] + {l : List (α × β)} : + (ofList l).isEmpty = l.isEmpty := + DHashMap.Raw.Const.isEmpty_ofList + +@[simp] +theorem unitOfList_nil : + unitOfList ([] : List α) = ∅ := + ext DHashMap.Raw.Const.unitOfList_nil + +@[simp] +theorem unitOfList_singleton {k : α} : + unitOfList [k] = (∅ : Raw α Unit).insertIfNew k () := + ext DHashMap.Raw.Const.unitOfList_singleton + +theorem unitOfList_cons {hd : α} {tl : List α} : + unitOfList (hd :: tl) = insertManyIfNewUnit ((∅ : Raw α Unit).insertIfNew hd ()) tl := + ext DHashMap.Raw.Const.unitOfList_cons + +@[simp] +theorem contains_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (unitOfList l).contains k = l.contains k := + DHashMap.Raw.Const.contains_unitOfList + +@[simp] +theorem mem_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + k ∈ unitOfList l ↔ l.contains k := + DHashMap.Raw.Const.mem_unitOfList + +theorem getKey?_unitOfList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (contains_eq_false : l.contains k = false) : + getKey? (unitOfList l) k = none := + DHashMap.Raw.Const.getKey?_unitOfList_of_contains_eq_false contains_eq_false + +theorem getKey?_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getKey? (unitOfList l) k' = some k := + DHashMap.Raw.Const.getKey?_unitOfList_of_mem k_beq distinct mem + +theorem getKey_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) {h'} : + getKey (unitOfList l) k' h' = k := + DHashMap.Raw.Const.getKey_unitOfList_of_mem k_beq distinct mem + +theorem getKey!_unitOfList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k : α} + (contains_eq_false : l.contains k = false) : + getKey! (unitOfList l) k = default := + DHashMap.Raw.Const.getKey!_unitOfList_of_contains_eq_false contains_eq_false + +theorem getKey!_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + getKey! (unitOfList l) k' = k := + DHashMap.Raw.Const.getKey!_unitOfList_of_mem k_beq distinct mem + +theorem getKeyD_unitOfList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k fallback : α} + (contains_eq_false : l.contains k = false) : + getKeyD (unitOfList l) k fallback = fallback := + DHashMap.Raw.Const.getKeyD_unitOfList_of_contains_eq_false contains_eq_false + +theorem getKeyD_unitOfList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + getKeyD (unitOfList l) k' fallback = k := + DHashMap.Raw.Const.getKeyD_unitOfList_of_mem k_beq distinct mem + +theorem size_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (unitOfList l).size = l.length := + DHashMap.Raw.Const.size_unitOfList distinct + +theorem size_unitOfList_le [EquivBEq α] [LawfulHashable α] + {l : List α} : + (unitOfList l).size ≤ l.length := + DHashMap.Raw.Const.size_unitOfList_le + +@[simp] +theorem isEmpty_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} : + (unitOfList l).isEmpty = l.isEmpty := + DHashMap.Raw.Const.isEmpty_unitOfList + +@[simp] +theorem getElem?_unitOfList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (unitOfList l)[k]? = + if l.contains k then some () else none := + DHashMap.Raw.Const.get?_unitOfList + +@[simp] +theorem getElem_unitOfList + {l : List α} {k : α} {h} : + (unitOfList l)[k] = () := + DHashMap.Raw.Const.get_unitOfList (h:=h) + +@[simp] +theorem getElem!_unitOfList + {l : List α} {k : α} : + (unitOfList l)[k]! = () := + DHashMap.Raw.Const.get!_unitOfList + +@[simp] +theorem getD_unitOfList + {l : List α} {k : α} {fallback : Unit} : + getD (unitOfList l) k fallback = () := by + simp + end Raw end Std.HashMap diff --git a/src/Std/Data/HashSet/Basic.lean b/src/Std/Data/HashSet/Basic.lean index bbbb3517b4dd..2a75fd63fc39 100644 --- a/src/Std/Data/HashSet/Basic.lean +++ b/src/Std/Data/HashSet/Basic.lean @@ -162,6 +162,14 @@ for all `a`. @[inline] def toList (m : HashSet α) : List α := m.inner.keys +/-- +Creates a hash set from a list of elements. Note that unlike repeatedly calling `insert`, if the +collection contains multiple elements that are equal (with regard to `==`), then the last element +in the collection will be present in the returned hash set. +-/ +@[inline] def ofList [BEq α] [Hashable α] (l : List α) : HashSet α := + ⟨HashMap.unitOfList l⟩ + section Unverified /-! We currently do not provide lemmas for the functions below. -/ @@ -233,14 +241,6 @@ appearance. HashSet α := ⟨m.inner.insertManyIfNewUnit l⟩ -/-- -Creates a hash set from a list of elements. Note that unlike repeatedly calling `insert`, if the -collection contains multiple elements that are equal (with regard to `==`), then the last element -in the collection will be present in the returned hash set. --/ -@[inline] def ofList [BEq α] [Hashable α] (l : List α) : HashSet α := - ⟨HashMap.unitOfList l⟩ - /-- 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 diff --git a/src/Std/Data/HashSet/Lemmas.lean b/src/Std/Data/HashSet/Lemmas.lean index 232724f26c0d..b3c9d8b8858e 100644 --- a/src/Std/Data/HashSet/Lemmas.lean +++ b/src/Std/Data/HashSet/Lemmas.lean @@ -361,7 +361,7 @@ theorem isEmpty_toList [EquivBEq α] [LawfulHashable α] : HashMap.isEmpty_keys @[simp] -theorem contains_toList [EquivBEq α] [LawfulHashable α] {k : α}: +theorem contains_toList [EquivBEq α] [LawfulHashable α] {k : α} : m.toList.contains k = m.contains k := HashMap.contains_keys @@ -373,6 +373,222 @@ theorem mem_toList [LawfulBEq α] [LawfulHashable α] {k : α} : theorem distinct_toList [EquivBEq α] [LawfulHashable α]: m.toList.Pairwise (fun a b => (a == b) = false) := HashMap.distinct_keys + +@[simp] +theorem insertMany_nil : + insertMany m [] = m := + ext HashMap.insertManyIfNewUnit_nil + +@[simp] +theorem insertMany_list_singleton {k : α} : + insertMany m [k] = m.insert k := + ext HashMap.insertManyIfNewUnit_list_singleton + +theorem insertMany_cons {l : List α} {k : α} : + insertMany m (k :: l) = insertMany (m.insert k) l := + ext HashMap.insertManyIfNewUnit_cons + +@[simp] +theorem contains_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (insertMany m l).contains k = (m.contains k || l.contains k) := + HashMap.contains_insertManyIfNewUnit_list + +@[simp] +theorem mem_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + k ∈ insertMany m l ↔ k ∈ m ∨ l.contains k := + HashMap.mem_insertManyIfNewUnit_list + +theorem mem_of_mem_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (contains_eq_false : l.contains k = false) : + k ∈ insertMany m l → k ∈ m := + HashMap.mem_of_mem_insertManyIfNewUnit_list contains_eq_false + +theorem get?_insertMany_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] {l : List α} {k : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + get? (insertMany m l) k = none := + HashMap.getKey?_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + not_mem contains_eq_false + +theorem get?_insertMany_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + get? (insertMany m l) k' = some k := + HashMap.getKey?_insertManyIfNewUnit_list_of_not_mem_of_mem + k_beq not_mem distinct mem + +theorem get?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (mem : k ∈ m) : + get? (insertMany m l) k = get? m k := + HashMap.getKey?_insertManyIfNewUnit_list_of_mem mem + +theorem get_insertMany_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} + {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) {h} : + get (insertMany m l) k' h = k := + HashMap.getKey_insertManyIfNewUnit_list_of_not_mem_of_mem + k_beq not_mem distinct mem + +theorem get_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (mem : k ∈ m) {h} : + get (insertMany m l) k h = get m k mem := + HashMap.getKey_insertManyIfNewUnit_list_of_mem mem + +theorem get!_insertMany_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] [Inhabited α] {l : List α} {k : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + get! (insertMany m l) k = default := + HashMap.getKey!_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + not_mem contains_eq_false + +theorem get!_insertMany_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + get! (insertMany m l) k' = k := + HashMap.getKey!_insertManyIfNewUnit_list_of_not_mem_of_mem + k_beq not_mem distinct mem + +theorem get!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k : α} (mem : k ∈ m) : + get! (insertMany m l) k = get! m k := + HashMap.getKey!_insertManyIfNewUnit_list_of_mem mem + +theorem getD_insertMany_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] {l : List α} {k fallback : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + getD (insertMany m l) k fallback = fallback := + HashMap.getKeyD_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + not_mem contains_eq_false + +theorem getD_insertMany_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' fallback : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getD (insertMany m l) k' fallback = k := + HashMap.getKeyD_insertManyIfNewUnit_list_of_not_mem_of_mem + k_beq not_mem distinct mem + +theorem getD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k fallback : α} (mem : k ∈ m) : + getD (insertMany m l) k fallback = getD m k fallback := + HashMap.getKeyD_insertManyIfNewUnit_list_of_mem mem + +theorem size_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (∀ (a : α), a ∈ m → l.contains a = false) → + (insertMany m l).size = m.size + l.length := + HashMap.size_insertManyIfNewUnit_list distinct + +theorem size_le_size_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List α} : + m.size ≤ (insertMany m l).size := + HashMap.size_le_size_insertManyIfNewUnit_list + +theorem size_insertMany_list_le [EquivBEq α] [LawfulHashable α] + {l : List α} : + (insertMany m l).size ≤ m.size + l.length := + HashMap.size_insertManyIfNewUnit_list_le + +@[simp] +theorem isEmpty_insertMany_list [EquivBEq α] [LawfulHashable α] + {l : List α} : + (insertMany m l).isEmpty = (m.isEmpty && l.isEmpty) := + HashMap.isEmpty_insertManyIfNewUnit_list + +end + +section + +@[simp] +theorem ofList_nil : + ofList ([] : List α) = ∅ := + ext HashMap.unitOfList_nil + +@[simp] +theorem ofList_singleton {k : α} : + ofList [k] = (∅ : HashSet α).insert k := + ext HashMap.unitOfList_singleton + +theorem ofList_cons {hd : α} {tl : List α} : + ofList (hd :: tl) = + insertMany ((∅ : HashSet α).insert hd) tl := + ext HashMap.unitOfList_cons + +@[simp] +theorem contains_ofList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (ofList l).contains k = l.contains k := + HashMap.contains_unitOfList + +theorem get?_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (contains_eq_false : l.contains k = false) : + get? (ofList l) k = none := + HashMap.getKey?_unitOfList_of_contains_eq_false contains_eq_false + +theorem get?_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + get? (ofList l) k' = some k := + HashMap.getKey?_unitOfList_of_mem k_beq distinct mem + +theorem get_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) {h} : + get (ofList l) k' h = k := + HashMap.getKey_unitOfList_of_mem k_beq distinct mem + +theorem get!_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k : α} + (contains_eq_false : l.contains k = false) : + get! (ofList l) k = default := + HashMap.getKey!_unitOfList_of_contains_eq_false contains_eq_false + +theorem get!_ofList_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + get! (ofList l) k' = k := + HashMap.getKey!_unitOfList_of_mem k_beq distinct mem + +theorem getD_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k fallback : α} + (contains_eq_false : l.contains k = false) : + getD (ofList l) k fallback = fallback := + HashMap.getKeyD_unitOfList_of_contains_eq_false contains_eq_false + +theorem getD_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + getD (ofList l) k' fallback = k := + HashMap.getKeyD_unitOfList_of_mem k_beq distinct mem + +theorem size_ofList [EquivBEq α] [LawfulHashable α] + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (ofList l).size = l.length := + HashMap.size_unitOfList distinct + +theorem size_ofList_le [EquivBEq α] [LawfulHashable α] + {l : List α} : + (ofList l).size ≤ l.length := + HashMap.size_unitOfList_le + +@[simp] +theorem isEmpty_ofList [EquivBEq α] [LawfulHashable α] + {l : List α} : + (ofList l).isEmpty = l.isEmpty := + HashMap.isEmpty_unitOfList + end end Std.HashSet diff --git a/src/Std/Data/HashSet/Raw.lean b/src/Std/Data/HashSet/Raw.lean index d0a7dd010fcf..699dd5c8e66d 100644 --- a/src/Std/Data/HashSet/Raw.lean +++ b/src/Std/Data/HashSet/Raw.lean @@ -165,6 +165,14 @@ for all `a`. @[inline] def toList (m : Raw α) : List α := m.inner.keys +/-- +Creates a hash set from a list of elements. Note that unlike repeatedly calling `insert`, if the +collection contains multiple elements that are equal (with regard to `==`), then the last element +in the collection will be present in the returned hash set. +-/ +@[inline] def ofList [BEq α] [Hashable α] (l : List α) : Raw α := + ⟨HashMap.Raw.unitOfList l⟩ + section Unverified /-! We currently do not provide lemmas for the functions below. -/ @@ -231,14 +239,6 @@ appearance. Raw α := ⟨m.inner.insertManyIfNewUnit l⟩ -/-- -Creates a hash set from a list of elements. Note that unlike repeatedly calling `insert`, if the -collection contains multiple elements that are equal (with regard to `==`), then the last element -in the collection will be present in the returned hash set. --/ -@[inline] def ofList [BEq α] [Hashable α] (l : List α) : Raw α := - ⟨HashMap.Raw.unitOfList l⟩ - /-- 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 diff --git a/src/Std/Data/HashSet/RawLemmas.lean b/src/Std/Data/HashSet/RawLemmas.lean index 77dcaa5bcfd8..344cd8e2667f 100644 --- a/src/Std/Data/HashSet/RawLemmas.lean +++ b/src/Std/Data/HashSet/RawLemmas.lean @@ -367,22 +367,22 @@ theorem containsThenInsert_snd (h : m.WF) {k : α} : (m.containsThenInsert k).2 ext (HashMap.Raw.containsThenInsertIfNew_snd h.out) @[simp] -theorem length_toList [EquivBEq α] [LawfulHashable α] (h : m.WF): +theorem length_toList [EquivBEq α] [LawfulHashable α] (h : m.WF) : m.toList.length = m.size := HashMap.Raw.length_keys h.1 @[simp] -theorem isEmpty_toList [EquivBEq α] [LawfulHashable α] (h : m.WF): +theorem isEmpty_toList [EquivBEq α] [LawfulHashable α] (h : m.WF) : m.toList.isEmpty = m.isEmpty := HashMap.Raw.isEmpty_keys h.1 @[simp] -theorem contains_toList [EquivBEq α] [LawfulHashable α] {k : α} (h : m.WF): +theorem contains_toList [EquivBEq α] [LawfulHashable α] {k : α} (h : m.WF) : m.toList.contains k = m.contains k := HashMap.Raw.contains_keys h.1 @[simp] -theorem mem_toList [LawfulBEq α] [LawfulHashable α] (h : m.WF) {k : α}: +theorem mem_toList [LawfulBEq α] [LawfulHashable α] (h : m.WF) {k : α} : k ∈ m.toList ↔ k ∈ m := HashMap.Raw.mem_keys h.1 @@ -390,6 +390,222 @@ theorem distinct_toList [EquivBEq α] [LawfulHashable α] (h : m.WF) : m.toList.Pairwise (fun a b => (a == b) = false) := HashMap.Raw.distinct_keys h.1 +@[simp] +theorem insertMany_nil (h : m.WF) : + insertMany m [] = m := + ext (HashMap.Raw.insertManyIfNewUnit_nil h.1) + +@[simp] +theorem insertMany_list_singleton (h : m.WF) {k : α} : + insertMany m [k] = m.insert k := + ext (HashMap.Raw.insertManyIfNewUnit_list_singleton h.1) + +theorem insertMany_cons (h : m.WF) {l : List α} {k : α} : + insertMany m (k :: l) = insertMany (m.insert k) l := + ext (HashMap.Raw.insertManyIfNewUnit_cons h.1) + +@[simp] +theorem contains_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} {k : α} : + (insertMany m l).contains k = (m.contains k || l.contains k) := + HashMap.Raw.contains_insertManyIfNewUnit_list h.1 + +@[simp] +theorem mem_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} {k : α} : + k ∈ insertMany m l ↔ k ∈ m ∨ l.contains k := + HashMap.Raw.mem_insertManyIfNewUnit_list h.1 + +theorem mem_of_mem_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} {k : α} (contains_eq_false : l.contains k = false) : + k ∈ insertMany m l → k ∈ m := + HashMap.Raw.mem_of_mem_insertManyIfNewUnit_list h.1 contains_eq_false + +theorem get?_insertMany_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] (h : m.WF) {l : List α} {k : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + get? (insertMany m l) k = none := + HashMap.Raw.getKey?_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + h.1 not_mem contains_eq_false + +theorem get?_insertMany_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + get? (insertMany m l) k' = some k := + HashMap.Raw.getKey?_insertManyIfNewUnit_list_of_not_mem_of_mem + h.1 k_beq not_mem distinct mem + +theorem get?_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k : α} (mem : k ∈ m) : + get? (insertMany m l) k = get? m k := + HashMap.Raw.getKey?_insertManyIfNewUnit_list_of_mem h.1 mem + +theorem get_insertMany_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} + {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) {h'} : + get (insertMany m l) k' h' = k := + HashMap.Raw.getKey_insertManyIfNewUnit_list_of_not_mem_of_mem + h.1 k_beq not_mem distinct mem + +theorem get_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k : α} (mem : k ∈ m) {h₃} : + get (insertMany m l) k h₃ = get m k mem := + HashMap.Raw.getKey_insertManyIfNewUnit_list_of_mem h.1 mem + +theorem get!_insertMany_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] [Inhabited α] (h : m.WF) {l : List α} {k : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + get! (insertMany m l) k = default := + HashMap.Raw.getKey!_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + h.1 not_mem contains_eq_false + +theorem get!_insertMany_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] (h : m.WF) {l : List α} {k k' : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + get! (insertMany m l) k' = k := + HashMap.Raw.getKey!_insertManyIfNewUnit_list_of_not_mem_of_mem + h.1 k_beq not_mem distinct mem + +theorem get!_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] (h : m.WF) {l : List α} {k : α} (mem : k ∈ m) : + get! (insertMany m l) k = get! m k := + HashMap.Raw.getKey!_insertManyIfNewUnit_list_of_mem h.1 mem + +theorem getD_insertMany_list_of_not_mem_of_contains_eq_false + [EquivBEq α] [LawfulHashable α] (h : m.WF) {l : List α} {k fallback : α} + (not_mem : ¬ k ∈ m) (contains_eq_false : l.contains k = false) : + getD (insertMany m l) k fallback = fallback := + HashMap.Raw.getKeyD_insertManyIfNewUnit_list_of_not_mem_of_contains_eq_false + h.1 not_mem contains_eq_false + +theorem getD_insertMany_list_of_not_mem_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k k' fallback : α} (k_beq : k == k') + (not_mem : ¬ k ∈ m) + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + getD (insertMany m l) k' fallback = k := + HashMap.Raw.getKeyD_insertManyIfNewUnit_list_of_not_mem_of_mem + h.1 k_beq not_mem distinct mem + +theorem getD_insertMany_list_of_mem [EquivBEq α] [LawfulHashable α] + (h : m.WF) {l : List α} {k fallback : α} (mem : k ∈ m) : + getD (insertMany m l) k fallback = getD m k fallback := + HashMap.Raw.getKeyD_insertManyIfNewUnit_list_of_mem h.1 mem + +theorem size_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (∀ (a : α), a ∈ m → l.contains a = false) → + (insertMany m l).size = m.size + l.length := + HashMap.Raw.size_insertManyIfNewUnit_list h.1 distinct + +theorem size_le_size_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} : + m.size ≤ (insertMany m l).size := + HashMap.Raw.size_le_size_insertManyIfNewUnit_list h.1 + +theorem size_insertMany_list_le [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} : + (insertMany m l).size ≤ m.size + l.length := + HashMap.Raw.size_insertManyIfNewUnit_list_le h.1 + +@[simp] +theorem isEmpty_insertMany_list [EquivBEq α] [LawfulHashable α] (h : m.WF) + {l : List α} : + (insertMany m l).isEmpty = (m.isEmpty && l.isEmpty) := + HashMap.Raw.isEmpty_insertManyIfNewUnit_list h.1 + +@[simp] +theorem ofList_nil : + ofList ([] : List α) = ∅ := + ext HashMap.Raw.unitOfList_nil + +@[simp] +theorem ofList_singleton {k : α} : + ofList [k] = (∅ : Raw α).insert k := + ext HashMap.Raw.unitOfList_singleton + +theorem ofList_cons {hd : α} {tl : List α} : + ofList (hd :: tl) = insertMany ((∅ : Raw α).insert hd) tl := + ext HashMap.Raw.unitOfList_cons + +@[simp] +theorem contains_ofList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + (ofList l).contains k = l.contains k := + HashMap.Raw.contains_unitOfList + +@[simp] +theorem mem_ofList [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} : + k ∈ ofList l ↔ l.contains k := + HashMap.Raw.mem_unitOfList + +theorem get?_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k : α} (contains_eq_false : l.contains k = false) : + get? (ofList l) k = none := + HashMap.Raw.getKey?_unitOfList_of_contains_eq_false contains_eq_false + +theorem get?_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) (mem : k ∈ l) : + get? (ofList l) k' = some k := + HashMap.Raw.getKey?_unitOfList_of_mem k_beq distinct mem + +theorem get_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} + {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) {h'} : + get (ofList l) k' h' = k := + HashMap.Raw.getKey_unitOfList_of_mem k_beq distinct mem + +theorem get!_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k : α} + (contains_eq_false : l.contains k = false) : + get! (ofList l) k = default := + HashMap.Raw.getKey!_unitOfList_of_contains_eq_false contains_eq_false + +theorem get!_ofList_of_mem [EquivBEq α] [LawfulHashable α] + [Inhabited α] {l : List α} {k k' : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + get! (ofList l) k' = k := + HashMap.Raw.getKey!_unitOfList_of_mem k_beq distinct mem + +theorem getD_ofList_of_contains_eq_false [EquivBEq α] [LawfulHashable α] + {l : List α} {k fallback : α} + (contains_eq_false : l.contains k = false) : + getD (ofList l) k fallback = fallback := + HashMap.Raw.getKeyD_unitOfList_of_contains_eq_false contains_eq_false + +theorem getD_ofList_of_mem [EquivBEq α] [LawfulHashable α] + {l : List α} {k k' fallback : α} (k_beq : k == k') + (distinct : l.Pairwise (fun a b => (a == b) = false)) + (mem : k ∈ l) : + getD (ofList l) k' fallback = k := + HashMap.Raw.getKeyD_unitOfList_of_mem k_beq distinct mem + +theorem size_ofList [EquivBEq α] [LawfulHashable α] + {l : List α} + (distinct : l.Pairwise (fun a b => (a == b) = false)) : + (ofList l).size = l.length := + HashMap.Raw.size_unitOfList distinct + +theorem size_ofList_le [EquivBEq α] [LawfulHashable α] + {l : List α} : + (ofList l).size ≤ l.length := + HashMap.Raw.size_unitOfList_le + +@[simp] +theorem isEmpty_ofList [EquivBEq α] [LawfulHashable α] + {l : List α} : + (ofList l).isEmpty = l.isEmpty := + HashMap.Raw.isEmpty_unitOfList + end Raw end Std.HashSet