Skip to content

Commit 1997048

Browse files
committed
Define union and provide basic proof infrastructure
1 parent 5911cbc commit 1997048

File tree

7 files changed

+104
-23
lines changed

7 files changed

+104
-23
lines changed

src/Std/Data/DHashMap/Internal/Defs.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,10 @@ where
422422
r := ⟨r.1.insert a b, fun _ h hm => h (r.2 _ h hm)⟩
423423
return r
424424

425+
/-- Internal implementation detail of the hash map -/
426+
@[inline] def union [BEq α] [Hashable α] (m₁ m₂ : Raw₀ α β) : Raw₀ α β :=
427+
if m₁.1.size ≤ m₂.1.size then (m₂.insertMany m₁.1).1 else (m₁.insertMany m₂.1).1
428+
425429
section
426430

427431
variable {β : Type v}

src/Std/Data/DHashMap/Internal/Model.lean

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,13 @@ def insertListₘ [BEq α] [Hashable α] (m : Raw₀ α β) (l : List ((a : α)
390390
| .nil => m
391391
| .cons hd tl => insertListₘ (m.insert hd.1 hd.2) tl
392392

393+
/-- Internal implementation detail of the hash map -/
394+
def unionₘ [BEq α] [Hashable α] (m₁ m₂ : Raw₀ α β) : Raw₀ α β :=
395+
if m₁.1.size ≤ m₂.1.size then
396+
insertListₘ m₂ (toListModel m₁.1.buckets)
397+
else
398+
insertListₘ m₁ (toListModel m₂.1.buckets)
399+
393400
section
394401

395402
variable {β : Type v}
@@ -595,7 +602,8 @@ theorem map_eq_mapₘ (m : Raw₀ α β) (f : (a : α) → β a → δ a) :
595602
theorem filter_eq_filterₘ (m : Raw₀ α β) (f : (a : α) → β a → Bool) :
596603
m.filter f = m.filterₘ f := rfl
597604

598-
theorem insertMany_eq_insertListₘ [BEq α] [Hashable α] (m : Raw₀ α β) (l : List ((a : α) × β a)) : insertMany m l = insertListₘ m l := by
605+
theorem insertMany_eq_insertListₘ [BEq α] [Hashable α] (m : Raw₀ α β) (l : List ((a : α) × β a)) :
606+
insertMany m l = insertListₘ m l := by
599607
simp only [insertMany, Id.run_pure, Id.run_bind, pure_bind, List.forIn_pure_yield_eq_foldl]
600608
suffices ∀ (t : { m' // ∀ (P : Raw₀ α β → Prop),
601609
(∀ {m'' : Raw₀ α β} {a : α} {b : β a}, P m'' → P (m''.insert a b)) → P m → P m' }),

src/Std/Data/DHashMap/Internal/RawLemmas.lean

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ macro_rules
9696
| apply Raw.WF.alter₀ | apply Raw.WF.modify₀
9797
| apply Raw.WF.constAlter₀ | apply Raw.WF.constModify₀
9898
| apply Raw₀.wf_insertMany₀ | apply Raw₀.Const.wf_insertMany₀
99-
| apply Raw₀.Const.wf_insertManyIfNewUnit₀
99+
| apply Raw₀.Const.wf_insertManyIfNewUnit₀ | apply Raw₀.wf_union₀
100100
| apply Raw.WF.filter₀ | apply Raw₀.wf_map₀ | apply Raw₀.wf_filterMap₀
101101
| apply Raw.WF.emptyWithCapacity₀) <;> wf_trivial)
102102

@@ -111,6 +111,7 @@ private def modifyMap : Std.DHashMap Name (fun _ => Name) :=
111111
`erase, ``toListModel_erase⟩,
112112
`insertIfNew, ``toListModel_insertIfNew⟩,
113113
`insertMany, ``toListModel_insertMany_list⟩,
114+
`union, ``toListModel_union⟩,
114115
`Const.insertMany, ``Const.toListModel_insertMany_list⟩,
115116
`Const.insertManyIfNewUnit, ``Const.toListModel_insertManyIfNewUnit_list⟩,
116117
`alter, ``toListModel_alter⟩,
@@ -2440,14 +2441,11 @@ section Union
24402441

24412442
variable (m₁ m₂ : Raw₀ α β)
24422443

2443-
--Temporary: presumably we'll want to have this somewhere else (and redefine it in terms of `insertMany`?)
2444-
def union : Raw₀ α β := ⟨m₁.val.union m₂.val, sorry
2445-
24462444
variable {m₁ m₂}
24472445

24482446
@[simp]
24492447
theorem union_insert_emptyWithCapacity {k : α} {v : β k} [EquivBEq α] [LawfulHashable α] (h : m.val.WF) :
2450-
m.union (emptyWithCapacity.insert k v) = m.insert k v := by
2448+
m.union (emptyWithCapacity.insert k v) = m.insert k v := by
24512449
sorry
24522450

24532451
theorem contains_union_of_left [EquivBEq α] [LawfulHashable α] (h₁ : m₁.val.WF)
@@ -2464,7 +2462,7 @@ theorem contains_union_of_right [EquivBEq α] [LawfulHashable α] (h₁ : m₁.
24642462
theorem contains_union [EquivBEq α] [LawfulHashable α] (h₁ : m₁.val.WF)
24652463
(h₂ : m₂.val.WF) {k : α} :
24662464
(m₁.union m₂).contains k = (m₁.contains k || m₂.contains k) := by
2467-
sorry
2465+
simp_to_model [contains, union] using List.containsKey_insertSmallerList
24682466

24692467
@[simp]
24702468
theorem contains_union_iff [EquivBEq α] [LawfulHashable α] (h₁ : m₁.val.WF)

src/Std/Data/DHashMap/Internal/WF.lean

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ theorem wfImp_filter [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] {m
983983

984984
/-! # `insertListₘ` -/
985985

986-
theorem toListModel_insertListₘ [BEq α] [Hashable α] [EquivBEq α][LawfulHashable α]
986+
theorem toListModel_insertListₘ [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α]
987987
{m : Raw₀ α β} {l : List ((a : α) × β a)} (h : Raw.WFImp m.1) :
988988
Perm (toListModel (insertListₘ m l).1.buckets)
989989
(List.insertList (toListModel m.1.buckets) l) := by
@@ -995,6 +995,37 @@ theorem toListModel_insertListₘ [BEq α] [Hashable α] [EquivBEq α][LawfulHas
995995
apply Perm.trans (ih (wfImp_insert h))
996996
apply List.insertList_perm_of_perm_first (toListModel_insert h) (wfImp_insert h).distinct
997997

998+
/-! # `unionₘ` -/
999+
1000+
theorem insertMany_eq_insertListₘ_toListModel [BEq α] [Hashable α] (m m₂ : Raw₀ α β) :
1001+
insertMany m m₂.1 = insertListₘ m (toListModel m₂.1.buckets) := by
1002+
simp only [insertMany, bind_pure_comp, map_pure, bind_pure]
1003+
simp only [ForIn.forIn]
1004+
simp only [Raw.forIn_eq_forIn_toListModel, forIn_pure_yield_eq_foldl, Id.run_pure]
1005+
generalize toListModel m₂.val.buckets = l
1006+
suffices ∀ (t : { m' // ∀ (P : Raw₀ α β → Prop),
1007+
(∀ {m'' : Raw₀ α β} {a : α} {b : β a}, P m'' → P (m''.insert a b)) → P m → P m' }),
1008+
(List.foldl (fun m' p => ⟨m'.val.insert p.1 p.2, fun P h₁ h₂ => h₁ (m'.2 _ h₁ h₂)⟩) t l).val =
1009+
t.val.insertListₘ l from this _
1010+
intro t
1011+
induction l generalizing m with
1012+
| nil => simp [insertListₘ]
1013+
| cons hd tl ih =>
1014+
simp only [List.foldl_cons, insertListₘ]
1015+
apply ih
1016+
1017+
theorem union_eq_unionₘ [BEq α] [Hashable α] (m₁ m₂ : Raw₀ α β) :
1018+
union m₁ m₂ = unionₘ m₁ m₂ := by
1019+
rw [union, unionₘ]
1020+
split <;> rw [insertMany_eq_insertListₘ_toListModel]
1021+
1022+
theorem toListModel_unionₘ [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α]
1023+
{m₁ m₂ : Raw₀ α β} (h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) :
1024+
Perm (toListModel (unionₘ m₁ m₂).1.buckets)
1025+
(List.insertSmallerList (toListModel m₁.1.buckets) (toListModel m₂.1.buckets)) := by
1026+
rw [unionₘ, insertSmallerList, h₁.size_eq, h₂.size_eq]
1027+
split <;> exact toListModel_insertListₘ ‹_›
1028+
9981029
end Raw₀
9991030

10001031
namespace Raw
@@ -1134,6 +1165,22 @@ theorem toListModel_insertMany_list [BEq α] [Hashable α] [EquivBEq α] [Lawful
11341165
apply toListModel_insertListₘ
11351166
exact h
11361167

1168+
/-! # `union` -/
1169+
1170+
theorem wf_union₀ [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α]
1171+
{m₁ m₂ : Raw α β} {h₁ : 0 < m₁.buckets.size} {h₂ : 0 < m₂.buckets.size} (h'₁ : m₁.WF)
1172+
(h'₂ : m₂.WF) :
1173+
(Raw₀.union ⟨m₁, h₁⟩ ⟨m₂, h₂⟩).1.WF := by
1174+
rw [union]
1175+
split <;> exact wf_insertMany₀ ‹_›
1176+
1177+
theorem toListModel_union [BEq α] [Hashable α] [EquivBEq α] [LawfulHashable α] {m₁ m₂ : Raw₀ α β}
1178+
(h₁ : Raw.WFImp m₁.1) (h₂ : Raw.WFImp m₂.1) :
1179+
Perm (toListModel (m₁.union m₂).1.buckets)
1180+
(List.insertSmallerList (toListModel m₁.1.buckets) (toListModel m₂.1.buckets)) := by
1181+
rw [union_eq_unionₘ]
1182+
exact toListModel_unionₘ h₁ h₂
1183+
11371184
/-! # `Const.insertListₘ` -/
11381185

11391186
theorem Const.toListModel_insertListₘ {β : Type v} [BEq α] [Hashable α] [EquivBEq α]

src/Std/Data/DHashMap/Raw.lean

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -397,20 +397,6 @@ by `foldM`. -/
397397
def foldRev (f : δ → (a : α) → β a → δ) (init : δ) (b : Raw α β) : δ :=
398398
Id.run (Internal.foldRevM (pure <| f · · ·) init b)
399399

400-
/-- Carries out a monadic action on each mapping in the hash map in some order. -/
401-
@[inline] def forM (f : (a : α) → β a → m PUnit) (b : Raw α β) : m PUnit :=
402-
b.buckets.forM (AssocList.forM f)
403-
404-
/-- Support for the `for` loop construct in `do` blocks. -/
405-
@[inline] def forIn (f : (a : α) → β a → δ → m (ForInStep δ)) (init : δ) (b : Raw α β) : m δ :=
406-
ForIn.forIn b.buckets init (fun bucket acc => bucket.forInStep acc f)
407-
408-
instance : ForM m (Raw α β) ((a : α) × β a) where
409-
forM m f := m.forM (fun a b => f ⟨a, b⟩)
410-
411-
instance : ForIn m (Raw α β) ((a : α) × β a) where
412-
forIn m init f := m.forIn (fun a b acc => f ⟨a, b⟩ acc) init
413-
414400
namespace Const
415401

416402
variable {β : Type v}

src/Std/Data/DHashMap/RawDef.lean

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ This file defines the type `Std.Data.DHashMap.Raw`. All of its functions are def
1616
set_option linter.missingDocs true
1717
set_option autoImplicit false
1818

19-
universe u v
19+
universe u v w
2020

2121
namespace Std.DHashMap
2222

23+
open Internal
24+
2325
/--
2426
Dependent hash maps without a bundled well-formedness invariant, suitable for use in nested
2527
inductive types. The well-formedness invariant is called `Raw.WF`. When in doubt, prefer `DHashMap`
@@ -46,4 +48,24 @@ structure Raw (α : Type u) (β : α → Type v) where
4648
/-- Internal implementation detail of the hash map -/
4749
buckets : Array (DHashMap.Internal.AssocList α β)
4850

51+
namespace Raw
52+
53+
variable {α : Type u} {β : α → Type v} {δ : Type w} {m : Type w → Type w}
54+
55+
/-- Carries out a monadic action on each mapping in the hash map in some order. -/
56+
@[inline] def forM [Monad m] (f : (a : α) → β a → m PUnit) (b : Raw α β) : m PUnit :=
57+
b.buckets.forM (AssocList.forM f)
58+
59+
/-- Support for the `for` loop construct in `do` blocks. -/
60+
@[inline] def forIn [Monad m] (f : (a : α) → β a → δ → m (ForInStep δ)) (init : δ) (b : Raw α β) : m δ :=
61+
ForIn.forIn b.buckets init (fun bucket acc => bucket.forInStep acc f)
62+
63+
instance x : ForM m (Raw α β) ((a : α) × β a) where
64+
forM m f := m.forM (fun a b => f ⟨a, b⟩)
65+
66+
instance : ForIn m (Raw α β) ((a : α) × β a) where
67+
forIn m init f := m.forIn (fun a b acc => f ⟨a, b⟩ acc) init
68+
69+
end Raw
70+
4971
end Std.DHashMap

src/Std/Data/Internal/List/Associative.lean

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2972,6 +2972,22 @@ theorem isEmpty_insertList [BEq α]
29722972
rw [insertList, List.isEmpty_cons, ih, isEmpty_insertEntry]
29732973
simp
29742974

2975+
/-- Internal implementation detail of the hash map -/
2976+
def insertSmallerList [BEq α] (l₁ l₂ : List ((a : α) × β a)) : List ((a : α) × β a) :=
2977+
if l₁.length ≤ l₂.length then insertList l₂ l₁ else insertList l₁ l₂
2978+
2979+
theorem DistinctKeys.insertSmallerList [BEq α] [PartialEquivBEq α] {l₁ l₂ : List ((a : α) × β a)}
2980+
(h₁ : DistinctKeys l₁) (h₂ : DistinctKeys l₂) : DistinctKeys (insertSmallerList l₁ l₂) := by
2981+
rw [List.insertSmallerList]
2982+
split <;> exact DistinctKeys.insertList ‹_›
2983+
2984+
theorem containsKey_insertSmallerList [BEq α] [PartialEquivBEq α] {l₁ l₂ : List ((a : α) × β a)}
2985+
{k : α} : containsKey k (List.insertSmallerList l₁ l₂) = (containsKey k l₁ || containsKey k l₂) := by
2986+
rw [List.insertSmallerList]
2987+
split
2988+
· rw [containsKey_insertList, ← containsKey_eq_contains_map_fst, Bool.or_comm]
2989+
· rw [containsKey_insertList, ← containsKey_eq_contains_map_fst]
2990+
29752991
section
29762992

29772993
variable {β : Type v}

0 commit comments

Comments
 (0)