feat: verify fold/for variants for Hashmaps (#7137)

This PR verifies the various fold and for variants for hashmaps.

---------

Co-authored-by: Markus Himmel <markus@himmel-villmar.de>
This commit is contained in:
Johannes Tantow 2025-02-21 17:08:33 +01:00 committed by GitHub
parent 6e77bee098
commit 0c35ca2e39
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 712 additions and 98 deletions

View file

@ -188,14 +188,6 @@ end
(m : DHashMap α (fun _ => β)) : List (α × β) :=
Raw.Const.toList m.1
section Unverified
/-! We currently do not provide lemmas for the functions below. -/
@[inline, inherit_doc Raw.filter] def filter (f : (a : α) → β a → Bool)
(m : DHashMap α β) : DHashMap α β :=
⟨Raw₀.filter f ⟨m.1, m.2.size_buckets_pos⟩, .filter₀ m.2⟩
@[inline, inherit_doc Raw.foldM] def foldM (f : δ → (a : α) → β a → m δ)
(init : δ) (b : DHashMap α β) : m δ :=
b.1.foldM f init
@ -204,15 +196,6 @@ section Unverified
(init : δ) (b : DHashMap α β) : δ :=
b.1.fold f init
/-- Partition a hash map into two hash map based on a predicate. -/
@[inline] def partition (f : (a : α) → β a → Bool)
(m : DHashMap α β) : DHashMap α β × DHashMap α β :=
m.fold (init := (∅, ∅)) fun ⟨l, r⟩ a b =>
if f a b then
(l.insert a b, r)
else
(l, r.insert a b)
@[inline, inherit_doc Raw.forM] def forM (f : (a : α) → β a → m PUnit)
(b : DHashMap α β) : m PUnit :=
b.1.forM f
@ -227,6 +210,23 @@ instance [BEq α] [Hashable α] : ForM m (DHashMap α β) ((a : α) × β a) whe
instance [BEq α] [Hashable α] : ForIn m (DHashMap α β) ((a : α) × β a) where
forIn m init f := m.forIn (fun a b acc => f ⟨a, b⟩ acc) init
section Unverified
/-! We currently do not provide lemmas for the functions below. -/
@[inline, inherit_doc Raw.filter] def filter (f : (a : α) → β a → Bool)
(m : DHashMap α β) : DHashMap α β :=
⟨Raw₀.filter f ⟨m.1, m.2.size_buckets_pos⟩, .filter₀ m.2⟩
/-- Partition a hash map into two hash map based on a predicate. -/
@[inline] def partition (f : (a : α) → β a → Bool)
(m : DHashMap α β) : DHashMap α β × DHashMap α β :=
m.fold (init := (∅, ∅)) fun ⟨l, r⟩ a b =>
if f a b then
(l.insert a b, r)
else
(l, r.insert a b)
@[inline, inherit_doc Raw.toArray] def toArray (m : DHashMap α β) :
Array ((a : α) × β a) :=
m.1.toArray

View file

@ -19,7 +19,7 @@ set_option autoImplicit false
open Std.Internal.List
open Std.Internal
universe u v
universe u v w
variable {α : Type u} {β : α → Type v}
@ -90,7 +90,10 @@ private def queryNames : Array Name :=
``Const.get!_eq_getValue!, ``Const.getD_eq_getValueD, ``getKey?_eq_getKey?,
``getKey_eq_getKey, ``getKeyD_eq_getKeyD, ``getKey!_eq_getKey!,
``Raw.toList_eq_toListModel, ``Raw.keys_eq_keys_toListModel,
``Raw.Const.toList_eq_toListModel_map]
``Raw.Const.toList_eq_toListModel_map, ``Raw.foldM_eq_foldlM_toListModel,
``Raw.fold_eq_foldl_toListModel, ``Raw.foldRevM_eq_foldrM_toListModel,
``Raw.foldRev_eq_foldr_toListModel, ``Raw.forIn_eq_forIn_toListModel,
``Raw.forM_eq_forM_toListModel]
private def modifyMap : Std.DHashMap Name (fun _ => Name) :=
.ofList
@ -936,6 +939,102 @@ theorem distinct_keys_toList [EquivBEq α] [LawfulHashable α] (h : m.1.WF) :
end Const
section monadic
-- The types are redefined because fold/for does not need BEq/Hashable
variable {α : Type u} {β : α → Type v} (m : Raw₀ α β) {δ : Type w} {m' : Type w → Type w}
theorem foldM_eq_foldlM_toList [Monad m'] [LawfulMonad m']
{f : δ → (a : α) → β a → m' δ} {init : δ} :
m.1.foldM f init = m.1.toList.foldlM (fun a b => f a b.1 b.2) init := by
simp_to_model
theorem fold_eq_foldl_toList {f : δ → (a : α) → β a → δ} {init : δ} :
m.1.fold f init = m.1.toList.foldl (fun a b => f a b.1 b.2) init := by
simp_to_model
theorem foldRevM_eq_foldrM_toList [Monad m'] [LawfulMonad m']
{f : δ → (a : α) → β a → m' δ} {init : δ} :
m.1.foldRevM f init = m.1.toList.foldrM (fun a b => f b a.1 a.2) init := by
simp_to_model
theorem foldRev_eq_foldr_toList {f : δ → (a : α) → β a → δ} {init : δ} :
m.1.foldRev f init = m.1.toList.foldr (fun a b => f b a.1 a.2) init := by
simp_to_model
theorem forM_eq_forM_toList [Monad m'] [LawfulMonad m'] {f : (a : α) → β a → m' PUnit} :
m.1.forM f = m.1.toList.forM (fun a => f a.1 a.2) := by
simp_to_model
theorem forIn_eq_forIn_toList [Monad m'] [LawfulMonad m']
{f : (a : α) → β a → δ → m' (ForInStep δ)} {init : δ} :
m.1.forIn f init = ForIn.forIn m.1.toList init (fun a b => f a.1 a.2 b) := by
simp_to_model
namespace Const
variable {β : Type v} (m : Raw₀ α (fun _ => β))
theorem foldM_eq_foldlM_toList [Monad m'] [LawfulMonad m']
{f : δ → (a : α) → β → m' δ} {init : δ} :
m.1.foldM f init = (Raw.Const.toList m.1).foldlM (fun a b => f a b.1 b.2) init := by
simp_to_model using List.foldlM_eq_foldlM_toProd
theorem fold_eq_foldl_toList {f : δ → (a : α) → β → δ} {init : δ} :
m.1.fold f init = (Raw.Const.toList m.1).foldl (fun a b => f a b.1 b.2) init := by
simp_to_model using List.foldl_eq_foldl_toProd
theorem foldRevM_eq_foldrM_toList [Monad m'] [LawfulMonad m']
{f : δ → (a : α) → β → m' δ} {init : δ} :
m.1.foldRevM f init = (Raw.Const.toList m.1).foldrM (fun a b => f b a.1 a.2) init := by
simp_to_model using List.foldrM_eq_foldrM_toProd
theorem foldRev_eq_foldr_toList {f : δ → (a : α) → β → δ} {init : δ} :
m.1.foldRev f init = (Raw.Const.toList m.1).foldr (fun a b => f b a.1 a.2) init := by
simp_to_model using List.foldr_eq_foldr_toProd
theorem forM_eq_forM_toList [Monad m'] [LawfulMonad m'] {f : (a : α) → β → m' PUnit} :
m.1.forM f = (Raw.Const.toList m.1).forM (fun a => f a.1 a.2) := by
simp_to_model using List.forM_eq_forM_toProd
theorem forIn_eq_forIn_toList [Monad m'] [LawfulMonad m']
{f : (a : α) → β → δ → m' (ForInStep δ)} {init : δ} :
m.1.forIn f init = ForIn.forIn (Raw.Const.toList m.1) init (fun a b => f a.1 a.2 b) := by
simp_to_model using List.forIn_eq_forIn_toProd
variable (m : Raw₀ α (fun _ => Unit))
theorem foldM_eq_foldlM_keys [Monad m'] [LawfulMonad m']
{f : δ → α → m' δ} {init : δ} :
m.1.foldM (fun d a _ => f d a) init = m.1.keys.foldlM f init := by
simp_to_model using List.foldlM_eq_foldlM_keys
theorem fold_eq_foldl_keys {f : δ → α → δ} {init : δ} :
m.1.fold (fun d a _ => f d a) init = m.1.keys.foldl f init := by
simp_to_model using List.foldl_eq_foldl_keys
theorem foldRevM_eq_foldrM_keys [Monad m'] [LawfulMonad m']
{f : δ → (a : α) → m' δ} {init : δ} :
m.1.foldRevM (fun d a _ => f d a) init = m.1.keys.foldrM (fun a b => f b a) init := by
simp_to_model using List.foldrM_eq_foldrM_keys
theorem foldRev_eq_foldr_keys {f : δ → (a : α) → δ} {init : δ} :
m.1.foldRev (fun d a _ => f d a) init = m.1.keys.foldr (fun a b => f b a) init := by
simp_to_model using List.foldr_eq_foldr_keys
theorem forM_eq_forM_keys [Monad m'] [LawfulMonad m'] {f : α → m' PUnit} :
m.1.forM (fun a _ => f a) = m.1.keys.forM f := by
simp_to_model using List.forM_eq_forM_keys
theorem forIn_eq_forIn_keys [Monad m'] [LawfulMonad m']
{f : α → δ → m' (ForInStep δ)} {init : δ} :
m.1.forIn (fun a _ d => f a d) init = ForIn.forIn m.1.keys init f := by
simp_to_model using List.forIn_eq_forIn_keys
end Const
end monadic
@[simp]
theorem insertMany_nil :
m.insertMany [] = m := by

View file

@ -111,6 +111,48 @@ theorem foldRev_cons_key {l : Raw α β} {acc : List α} :
l.foldRev (fun acc k _ => k :: acc) acc = List.keys (toListModel l.buckets) ++ acc := by
rw [foldRev_cons_apply, keys_eq_map]
theorem foldM_eq_foldlM_toListModel {δ : Type w} {m : Type w → Type w } [Monad m] [LawfulMonad m]
{f : δ → (a : α) → β a → m δ} {init : δ} {b : Raw α β} :
b.foldM f init = (toListModel b.buckets).foldlM (fun a b => f a b.1 b.2) init := by
simp only [Raw.foldM, ← Array.foldlM_toList, toListModel]
induction b.buckets.toList generalizing init with
| nil => simp
| cons hd tl ih =>
simp only [foldlM_cons, ih, flatMap_cons, foldlM_append]
congr
induction hd generalizing init with
| nil => simp [AssocList.foldlM]
| cons hda hdb tl ih =>
simp only [AssocList.foldlM, AssocList.toList_cons, foldlM_cons]
congr
funext init'
rw [ih]
theorem fold_eq_foldl_toListModel {l : Raw α β} {f : γ → (a : α) → β a → γ} {init : γ} :
l.fold f init = (toListModel l.buckets).foldl (fun a b => f a b.1 b.2) init := by
simp [Raw.fold, foldM_eq_foldlM_toListModel]
theorem foldRevM_eq_foldrM_toListModel {δ : Type w} {m : Type w → Type w } [Monad m] [LawfulMonad m]
{f : δ → (a : α) → β a → m δ} {init : δ} {b : Raw α β} :
b.foldRevM f init = (toListModel b.buckets).foldrM (fun a b => f b a.1 a.2) init := by
simp only [Raw.foldRevM, ← Array.foldrM_toList, toListModel]
induction b.buckets.toList generalizing init with
| nil => simp
| cons hd tl ih =>
simp only [foldrM_cons, ih, flatMap_cons, foldrM_append]
congr
funext init'
induction hd generalizing init' with
| nil => simp [AssocList.foldrM]
| cons hda hdb tl ih =>
simp only [AssocList.foldrM, AssocList.toList_cons, foldrM_cons]
congr
rw [ih]
theorem foldRev_eq_foldr_toListModel {l : Raw α β} {f : γ → (a : α) → β a → γ} {init : γ} :
l.foldRev f init = (toListModel l.buckets).foldr (fun a b => f b a.1 a.2) init := by
simp [Raw.foldRev, foldRevM_eq_foldrM_toListModel]
theorem toList_eq_toListModel {m : Raw α β} : m.toList = toListModel m.buckets := by
simp [Raw.toList, foldRev_cons]
@ -122,6 +164,44 @@ theorem keys_eq_keys_toListModel {m : Raw α β }:
m.keys = List.keys (toListModel m.buckets) := by
simp [Raw.keys, foldRev_cons_key, keys_eq_map]
theorem forM_eq_forM_toListModel {l: Raw α β} {m : Type w → Type w} [Monad m] [LawfulMonad m]
{f : (a : α) → β a → m PUnit} :
l.forM f = (toListModel l.buckets).forM (fun a => f a.1 a.2) := by
simp only [Raw.forM, Array.forM, ← Array.foldlM_toList, toListModel]
induction l.buckets.toList with
| nil => simp
| cons hd tl ih =>
simp only [foldlM_cons, flatMap_cons, forM_eq_forM, forM_append]
congr
· simp [AssocList.forM]
induction hd with
| nil => simp [AssocList.forM, AssocList.foldlM]
| cons hda hdb tl ih =>
simp only [AssocList.foldlM, AssocList.toList_cons, forM_cons]
congr
funext x
rw [ih]
· funext x
simp [ih]
theorem forIn_eq_forIn_toListModel {δ : Type w} {l : Raw α β} {m : Type w → Type w} [Monad m] [LawfulMonad m]
{f : (a : α) → β a → δ → m (ForInStep δ)} {init : δ} :
l.forIn f init = ForIn.forIn (toListModel l.buckets) init (fun a d => f a.1 a.2 d) := by
rw [Raw.forIn, ← Array.forIn_toList, toListModel]
induction l.buckets.toList generalizing init with
| nil => simp
| cons hd tl ih =>
induction hd generalizing init with
| nil => simpa [AssocList.forInStep, AssocList.forInStep.go] using ih
| cons k v tl' ih' =>
simp only [AssocList.forInStep, forIn_cons, AssocList.forInStep.go, LawfulMonad.bind_assoc,
flatMap_cons, AssocList.toList_cons, cons_append]
congr
apply funext
rintro (⟨d⟩|⟨d⟩)
· simp
· simpa using ih'
end Raw
namespace Raw₀

View file

@ -20,7 +20,7 @@ open Std.DHashMap.Internal
set_option linter.missingDocs true
set_option autoImplicit false
universe u v
universe u v w
variable {α : Type u} {β : α → Type v} {_ : BEq α} {_ : Hashable α}
@ -1066,6 +1066,83 @@ theorem distinct_keys_toList [EquivBEq α] [LawfulHashable α] :
end Const
section monadic
variable {m : DHashMap α β} {δ : Type w} {m' : Type w → Type w}
theorem foldM_eq_foldlM_toList [Monad m'] [LawfulMonad m']
{f : δ → (a : α) → β a → m' δ} {init : δ} :
m.foldM f init = m.toList.foldlM (fun a b => f a b.1 b.2) init :=
Raw₀.foldM_eq_foldlM_toList ⟨m.1, m.2.size_buckets_pos⟩
theorem fold_eq_foldl_toList {f : δ → (a : α) → β a → δ} {init : δ} :
m.fold f init = m.toList.foldl (fun a b => f a b.1 b.2) init :=
Raw₀.fold_eq_foldl_toList ⟨m.1, m.2.size_buckets_pos⟩
@[simp]
theorem forM_eq_forM [Monad m'] [LawfulMonad m'] {f : (a : α) → β a → m' PUnit} :
DHashMap.forM f m = ForM.forM m (fun a => f a.1 a.2):= rfl
theorem forM_eq_forM_toList [Monad m'] [LawfulMonad m'] {f : (a : α) × β a → m' PUnit} :
ForM.forM m f = ForM.forM m.toList f :=
Raw₀.forM_eq_forM_toList ⟨m.1, m.2.size_buckets_pos⟩
@[simp]
theorem forIn_eq_forIn [Monad m'] [LawfulMonad m']
{f : (a : α) → β a → δ → m' (ForInStep δ)} {init : δ} :
DHashMap.forIn f init m = ForIn.forIn m init (fun a b => f a.1 a.2 b) := rfl
theorem forIn_eq_forIn_toList [Monad m'] [LawfulMonad m']
{f : (a : α) × β a → δ → m' (ForInStep δ)} {init : δ} :
ForIn.forIn m init f = ForIn.forIn m.toList init f :=
Raw₀.forIn_eq_forIn_toList ⟨m.1, m.2.size_buckets_pos⟩
namespace Const
variable {β : Type v} {m : DHashMap α (fun _ => β)}
theorem foldM_eq_foldlM_toList [Monad m'] [LawfulMonad m']
{f : δ → (a : α) → β → m' δ} {init : δ} :
m.foldM f init = (Const.toList m).foldlM (fun a b => f a b.1 b.2) init :=
Raw₀.Const.foldM_eq_foldlM_toList ⟨m.1, m.2.size_buckets_pos⟩
theorem fold_eq_foldl_toList {f : δ → (a : α) → β → δ} {init : δ} :
m.fold f init = (Const.toList m).foldl (fun a b => f a b.1 b.2) init :=
Raw₀.Const.fold_eq_foldl_toList ⟨m.1, m.2.size_buckets_pos⟩
theorem forM_eq_forM_toList [Monad m'] [LawfulMonad m'] {f : (a : α) → β → m' PUnit} :
m.forM f = (Const.toList m).forM (fun a => f a.1 a.2) :=
Raw₀.Const.forM_eq_forM_toList ⟨m.1, m.2.size_buckets_pos⟩
theorem forIn_eq_forIn_toList [Monad m'] [LawfulMonad m']
{f : (a : α) → β → δ → m' (ForInStep δ)} {init : δ} :
m.forIn f init = ForIn.forIn (Const.toList m) init (fun a b => f a.1 a.2 b) :=
Raw₀.Const.forIn_eq_forIn_toList ⟨m.1, m.2.size_buckets_pos⟩
variable {m : DHashMap α (fun _ => Unit)}
theorem foldM_eq_foldlM_keys [Monad m'] [LawfulMonad m']
{f : δ → α → m' δ} {init : δ} :
m.foldM (fun d a _ => f d a) init = m.keys.foldlM f init :=
Raw₀.Const.foldM_eq_foldlM_keys ⟨m.1, m.2.size_buckets_pos⟩
theorem fold_eq_foldl_keys {f : δ → α → δ} {init : δ} :
m.fold (fun d a _ => f d a) init = m.keys.foldl f init :=
Raw₀.Const.fold_eq_foldl_keys ⟨m.1, m.2.size_buckets_pos⟩
theorem forM_eq_forM_keys [Monad m'] [LawfulMonad m'] {f : α → m' PUnit} :
m.forM (fun a _ => f a) = m.keys.forM f :=
Raw₀.Const.forM_eq_forM_keys ⟨m.1, m.2.size_buckets_pos⟩
theorem forIn_eq_forIn_keys [Monad m'] [LawfulMonad m']
{f : α → δ → m' (ForInStep δ)} {init : δ} :
m.forIn (fun a _ d => f a d) init = ForIn.forIn m.keys init f :=
Raw₀.Const.forIn_eq_forIn_keys ⟨m.1, m.2.size_buckets_pos⟩
end Const
end monadic
@[simp]
theorem insertMany_nil :
m.insertMany [] = m :=

View file

@ -335,32 +335,6 @@ This function ensures that the value is used linearly.
else
section Unverified
/-! We currently do not provide lemmas for the functions below. -/
/--
Updates the values of the hash map by applying the given function to all mappings, keeping
only those mappings where the function returns `some` value.
-/
@[inline] def filterMap {γ : α → Type w} (f : (a : α) → β a → Option (γ a)) (m : Raw α β) :
Raw α γ :=
if h : 0 < m.buckets.size then
Raw₀.filterMap f ⟨m, h⟩
else ∅ -- will never happen for well-formed inputs
/-- Updates the values of the hash map by applying the given function to all mappings. -/
@[inline] def map {γ : α → Type w} (f : (a : α) → β a → γ a) (m : Raw α β) : Raw α γ :=
if h : 0 < m.buckets.size then
Raw₀.map f ⟨m, h⟩
else ∅ -- will never happen for well-formed inputs
/-- Removes all mappings of the hash map for which the given function returns `false`. -/
@[inline] def filter (f : (a : α) → β a → Bool) (m : Raw α β) : Raw α β :=
if h : 0 < m.buckets.size then
Raw₀.filter f ⟨m, h⟩
else ∅ -- will never happen for well-formed inputs
/--
Monadically computes a value by folding the given function over the mappings in the hash
map in some order.
@ -399,6 +373,32 @@ instance : ForM m (Raw α β) ((a : α) × β a) where
instance : ForIn m (Raw α β) ((a : α) × β a) where
forIn m init f := m.forIn (fun a b acc => f ⟨a, b⟩ acc) init
section Unverified
/-! We currently do not provide lemmas for the functions below. -/
/--
Updates the values of the hash map by applying the given function to all mappings, keeping
only those mappings where the function returns `some` value.
-/
@[inline] def filterMap {γ : α → Type w} (f : (a : α) → β a → Option (γ a)) (m : Raw α β) :
Raw α γ :=
if h : 0 < m.buckets.size then
Raw₀.filterMap f ⟨m, h⟩
else ∅ -- will never happen for well-formed inputs
/-- Updates the values of the hash map by applying the given function to all mappings. -/
@[inline] def map {γ : α → Type w} (f : (a : α) → β a → γ a) (m : Raw α β) : Raw α γ :=
if h : 0 < m.buckets.size then
Raw₀.map f ⟨m, h⟩
else ∅ -- will never happen for well-formed inputs
/-- Removes all mappings of the hash map for which the given function returns `false`. -/
@[inline] def filter (f : (a : α) → β a → Bool) (m : Raw α β) : Raw α β :=
if h : 0 < m.buckets.size then
Raw₀.filter f ⟨m, h⟩
else ∅ -- will never happen for well-formed inputs
/-- Transforms the hash map into an array of mappings in some order. -/
@[inline] def toArray (m : Raw α β) : Array ((a : α) × β a) :=
m.fold (fun acc k v => acc.push ⟨k, v⟩) #[]

View file

@ -20,7 +20,7 @@ open Std.DHashMap.Internal
set_option linter.missingDocs true
set_option autoImplicit false
universe u v
universe u v w
variable {α : Type u} {β : α → Type v}
@ -1158,6 +1158,86 @@ theorem distinct_keys_toList [EquivBEq α] [LawfulHashable α] (h : m.WF) :
end Const
section monadic
variable {m : Raw α β} {δ : Type w} {m' : Type w → Type w}
theorem foldM_eq_foldlM_toList [Monad m'] [LawfulMonad m'] (h : m.WF)
{f : δ → (a : α) → β a → m' δ} {init : δ} :
m.foldM f init = m.toList.foldlM (fun a b => f a b.1 b.2) init :=
Raw₀.foldM_eq_foldlM_toList ⟨m, h.size_buckets_pos⟩
theorem fold_eq_foldl_toList (h : m.WF) {f : δ → (a : α) → β a → δ} {init : δ} :
m.fold f init = m.toList.foldl (fun a b => f a b.1 b.2) init :=
Raw₀.fold_eq_foldl_toList ⟨m, h.size_buckets_pos⟩
omit [BEq α] [Hashable α] in
@[simp]
theorem forM_eq_forM [Monad m'] [LawfulMonad m']
{f : (a : α) → β a → m' PUnit} :
Raw.forM f m = ForM.forM m (fun a => f a.1 a.2) := rfl
theorem forM_eq_forM_toList [Monad m'] [LawfulMonad m'] (h : m.WF) {f : (a : α) × β a → m' PUnit} :
ForM.forM m f = m.toList.forM f :=
Raw₀.forM_eq_forM_toList ⟨m, h.size_buckets_pos⟩
omit [BEq α] [Hashable α] in
@[simp]
theorem forIn_eq_forIn [Monad m'] [LawfulMonad m']
{f : (a : α) → β a → δ → m' (ForInStep δ)} {init : δ} :
Raw.forIn f init m = ForIn.forIn m init (fun a b => f a.1 a.2 b) := rfl
theorem forIn_eq_forIn_toList [Monad m'] [LawfulMonad m']
{f : (a : α) × β a → δ → m' (ForInStep δ)} {init : δ} (h : m.WF) :
ForIn.forIn m init f = ForIn.forIn m.toList init f :=
Raw₀.forIn_eq_forIn_toList ⟨m, h.size_buckets_pos⟩
namespace Const
variable {β : Type v} {m : Raw α (fun _ => β)}
theorem foldM_eq_foldlM_toList [Monad m'] [LawfulMonad m'] (h : m.WF)
{f : δ → (a : α) → β → m' δ} {init : δ} :
m.foldM f init = (Const.toList m).foldlM (fun a b => f a b.1 b.2) init :=
Raw₀.Const.foldM_eq_foldlM_toList ⟨m, h.size_buckets_pos⟩
theorem fold_eq_foldl_toList (h : m.WF) {f : δ → (a : α) → β → δ} {init : δ} :
m.fold f init = (Raw.Const.toList m).foldl (fun a b => f a b.1 b.2) init :=
Raw₀.Const.fold_eq_foldl_toList ⟨m, h.size_buckets_pos⟩
theorem forM_eq_forM_toList [Monad m'] [LawfulMonad m'] (h : m.WF) {f : (a : α) → β → m' PUnit} :
m.forM f = (Raw.Const.toList m).forM (fun a => f a.1 a.2) :=
Raw₀.Const.forM_eq_forM_toList ⟨m, h.size_buckets_pos⟩
theorem forIn_eq_forIn_toList [Monad m'] [LawfulMonad m'] (h : m.WF)
{f : (a : α) → β → δ → m' (ForInStep δ)} {init : δ} :
m.forIn f init = ForIn.forIn (Raw.Const.toList m) init (fun a b => f a.1 a.2 b) :=
Raw₀.Const.forIn_eq_forIn_toList ⟨m, h.size_buckets_pos⟩
variable {m : Raw α (fun _ => Unit)}
theorem foldM_eq_foldlM_keys [Monad m'] [LawfulMonad m'] (h : m.WF)
{f : δ → α → m' δ} {init : δ} :
m.foldM (fun d a _ => f d a) init = m.keys.foldlM f init :=
Raw₀.Const.foldM_eq_foldlM_keys ⟨m, h.size_buckets_pos⟩
theorem fold_eq_foldl_keys (h : m.WF) {f : δ → α → δ} {init : δ} :
m.fold (fun d a _ => f d a) init = m.keys.foldl f init :=
Raw₀.Const.fold_eq_foldl_keys ⟨m, h.size_buckets_pos⟩
theorem forM_eq_forM_keys [Monad m'] [LawfulMonad m'] (h : m.WF) {f : α → m' PUnit} :
m.forM (fun a _ => f a) = m.keys.forM f :=
Raw₀.Const.forM_eq_forM_keys ⟨m, h.size_buckets_pos⟩
theorem forIn_eq_forIn_keys [Monad m'] [LawfulMonad m'] (h : m.WF)
{f : α → δ → m' (ForInStep δ)} {init : δ} :
m.forIn (fun a _ d => f a d) init = ForIn.forIn m.keys init f :=
Raw₀.Const.forIn_eq_forIn_keys ⟨m, h.size_buckets_pos⟩
end Const
end monadic
@[simp]
theorem insertMany_nil [EquivBEq α] [LawfulHashable α] (h : m.WF) :
m.insertMany [] = m := by

View file

@ -203,19 +203,6 @@ instance [BEq α] [Hashable α] : GetElem? (HashMap α β) α β (fun m a => a
List (α × β) :=
DHashMap.Const.toList m.inner
section Unverified
/-! We currently do not provide lemmas for the functions below. -/
@[inline, inherit_doc DHashMap.filter] def filter (f : α → β → Bool)
(m : HashMap α β) : HashMap α β :=
⟨m.inner.filter f⟩
@[inline, inherit_doc DHashMap.partition] def partition (f : α → β → Bool)
(m : HashMap α β) : HashMap α β × HashMap α β :=
let ⟨l, r⟩ := m.inner.partition f
⟨⟨l⟩, ⟨r⟩⟩
@[inline, inherit_doc DHashMap.foldM] def foldM {m : Type w → Type w}
[Monad m] {γ : Type w} (f : γα → β → m γ) (init : γ) (b : HashMap α β) : m γ :=
b.inner.foldM f init
@ -238,6 +225,19 @@ instance [BEq α] [Hashable α] {m : Type w → Type w} : ForM m (HashMap α β)
instance [BEq α] [Hashable α] {m : Type w → Type w} : ForIn m (HashMap α β) (α × β) where
forIn m init f := m.forIn (fun a b acc => f (a, b) acc) init
section Unverified
/-! We currently do not provide lemmas for the functions below. -/
@[inline, inherit_doc DHashMap.filter] def filter (f : α → β → Bool)
(m : HashMap α β) : HashMap α β :=
⟨m.inner.filter f⟩
@[inline, inherit_doc DHashMap.partition] def partition (f : α → β → Bool)
(m : HashMap α β) : HashMap α β × HashMap α β :=
let ⟨l, r⟩ := m.inner.partition f
⟨⟨l⟩, ⟨r⟩⟩
@[inline, inherit_doc DHashMap.Const.toArray] def toArray (m : HashMap α β) :
Array (α × β) :=
DHashMap.Const.toArray m.inner

View file

@ -18,7 +18,7 @@ is to provide an instance of `LawfulBEq α`.
set_option linter.missingDocs true
set_option autoImplicit false
universe u v
universe u v w
variable {α : Type u} {β : Type v} {_ : BEq α} {_ : Hashable α}
@ -751,6 +751,59 @@ theorem distinct_keys_toList [EquivBEq α] [LawfulHashable α] :
m.toList.Pairwise (fun a b => (a.1 == b.1) = false) :=
DHashMap.Const.distinct_keys_toList
section monadic
variable {m : HashMap α β} {δ : Type w} {m' : Type w → Type w}
theorem foldM_eq_foldlM_toList [Monad m'] [LawfulMonad m']
{f : δ → (a : α) → β → m' δ} {init : δ} :
m.foldM f init = m.toList.foldlM (fun a b => f a b.1 b.2) init :=
DHashMap.Const.foldM_eq_foldlM_toList
theorem fold_eq_foldl_toList {f : δ → (a : α) → β → δ} {init : δ} :
m.fold f init = m.toList.foldl (fun a b => f a b.1 b.2) init :=
DHashMap.Const.fold_eq_foldl_toList
@[simp]
theorem forM_eq_forM [Monad m'] [LawfulMonad m'] {f : (a : α) → β → m' PUnit} :
m.forM f = ForM.forM m (fun a => f a.1 a.2) := rfl
theorem forM_eq_forM_toList [Monad m'] [LawfulMonad m'] {f : α × β → m' PUnit} :
ForM.forM m f = ForM.forM m.toList f :=
DHashMap.Const.forM_eq_forM_toList
@[simp]
theorem forIn_eq_forIn [Monad m'] [LawfulMonad m']
{f : (a : α) → β → δ → m' (ForInStep δ)} {init : δ} :
m.forIn f init = ForIn.forIn m init (fun a d => f a.1 a.2 d) := rfl
theorem forIn_eq_forIn_toList [Monad m'] [LawfulMonad m']
{f : α × β → δ → m' (ForInStep δ)} {init : δ} :
ForIn.forIn m init f = ForIn.forIn m.toList init f :=
DHashMap.Const.forIn_eq_forIn_toList
variable {m : DHashMap α (fun _ => Unit)}
theorem foldM_eq_foldlM_keys [Monad m'] [LawfulMonad m']
{f : δ → α → m' δ} {init : δ} :
m.foldM (fun d a _ => f d a) init = m.keys.foldlM f init :=
DHashMap.Const.foldM_eq_foldlM_keys
theorem fold_eq_foldl_keys {f : δ → α → δ} {init : δ} :
m.fold (fun d a _ => f d a) init = m.keys.foldl f init :=
DHashMap.Const.fold_eq_foldl_keys
theorem forM_eq_forM_keys [Monad m'] [LawfulMonad m'] {f : α → m' PUnit} :
m.forM (fun a _ => f a) = m.keys.forM f :=
DHashMap.Const.forM_eq_forM_keys
theorem forIn_eq_forIn_keys [Monad m'] [LawfulMonad m']
{f : α → δ → m' (ForInStep δ)} {init : δ} :
m.forIn (fun a _ d => f a d) init = ForIn.forIn m.keys init f :=
DHashMap.Const.forIn_eq_forIn_keys
end monadic
@[simp]
theorem insertMany_nil :
insertMany m [] = m :=

View file

@ -192,21 +192,6 @@ instance [BEq α] [Hashable α] : GetElem? (Raw α β) α β (fun m a => a ∈ m
@[inline, inherit_doc DHashMap.Raw.Const.toList] def toList (m : Raw α β) : List (α × β) :=
DHashMap.Raw.Const.toList m.inner
section Unverified
/-! We currently do not provide lemmas for the functions below. -/
@[inline, inherit_doc DHashMap.Raw.filterMap] def filterMap {γ : Type w} (f : α → β → Option γ)
(m : Raw α β) : Raw α γ :=
⟨m.inner.filterMap f⟩
@[inline, inherit_doc DHashMap.Raw.map] def map {γ : Type w} (f : α → β → γ) (m : Raw α β) :
Raw α γ :=
⟨m.inner.map f⟩
@[inline, inherit_doc DHashMap.Raw.filter] def filter (f : α → β → Bool) (m : Raw α β) : Raw α β :=
⟨m.inner.filter f⟩
@[inline, inherit_doc DHashMap.Raw.foldM] def foldM {m : Type w → Type w} [Monad m] {γ : Type w}
(f : γα → β → m γ) (init : γ) (b : Raw α β) : m γ :=
b.inner.foldM f init
@ -229,6 +214,21 @@ instance {m : Type w → Type w} : ForM m (Raw α β) (α × β) where
instance {m : Type w → Type w} : ForIn m (Raw α β) (α × β) where
forIn m init f := m.forIn (fun a b acc => f (a, b) acc) init
section Unverified
/-! We currently do not provide lemmas for the functions below. -/
@[inline, inherit_doc DHashMap.Raw.filterMap] def filterMap {γ : Type w} (f : α → β → Option γ)
(m : Raw α β) : Raw α γ :=
⟨m.inner.filterMap f⟩
@[inline, inherit_doc DHashMap.Raw.map] def map {γ : Type w} (f : α → β → γ) (m : Raw α β) :
Raw α γ :=
⟨m.inner.map f⟩
@[inline, inherit_doc DHashMap.Raw.filter] def filter (f : α → β → Bool) (m : Raw α β) : Raw α β :=
⟨m.inner.filter f⟩
@[inline, inherit_doc DHashMap.Raw.Const.toArray] def toArray (m : Raw α β) : Array (α × β) :=
DHashMap.Raw.Const.toArray m.inner

View file

@ -18,7 +18,7 @@ is to provide an instance of `LawfulBEq α`.
set_option linter.missingDocs true
set_option autoImplicit false
universe u v
universe u v w
variable {α : Type u} {β : Type v}
@ -758,6 +758,61 @@ theorem distinct_keys_toList [EquivBEq α] [LawfulHashable α] (h : m.WF) :
m.toList.Pairwise (fun a b => (a.1 == b.1) = false) :=
DHashMap.Raw.Const.distinct_keys_toList h.out
section monadic
variable {m : Raw α β} {δ : Type w} {m' : Type w → Type w}
theorem foldM_eq_foldlM_toList [Monad m'] [LawfulMonad m'] (h : m.WF)
{f : δ → (a : α) → β → m' δ} {init : δ} :
m.foldM f init = m.toList.foldlM (fun a b => f a b.1 b.2) init :=
DHashMap.Raw.Const.foldM_eq_foldlM_toList h.out
theorem fold_eq_foldl_toList (h : m.WF) {f : δ → (a : α) → β → δ} {init : δ} :
m.fold f init = m.toList.foldl (fun a b => f a b.1 b.2) init :=
DHashMap.Raw.Const.fold_eq_foldl_toList h.out
omit [BEq α] [Hashable α] in
@[simp]
theorem forM_eq_forM [Monad m'] [LawfulMonad m'] {f : (a : α) → β → m' PUnit} :
m.forM f = ForM.forM m (fun a => f a.1 a.2) := rfl
theorem forM_eq_forM_toList [Monad m'] [LawfulMonad m'] (h : m.WF) {f : α × β → m' PUnit} :
ForM.forM m f = ForM.forM m.toList f :=
DHashMap.Raw.Const.forM_eq_forM_toList h.out
omit [BEq α] [Hashable α] in
@[simp]
theorem forIn_eq_forIn [Monad m'] [LawfulMonad m']
{f : (a : α) → β → δ → m' (ForInStep δ)} {init : δ} :
m.forIn f init = ForIn.forIn m init (fun a d => f a.1 a.2 d) := rfl
theorem forIn_eq_forIn_toList [Monad m'] [LawfulMonad m'] (h : m.WF)
{f : α × β → δ → m' (ForInStep δ)} {init : δ} :
ForIn.forIn m init f = ForIn.forIn m.toList init f :=
DHashMap.Raw.Const.forIn_eq_forIn_toList h.out
variable {m : Raw α Unit}
theorem foldM_eq_foldlM_keys [Monad m'] [LawfulMonad m'] (h : m.WF)
{f : δ → α → m' δ} {init : δ} :
m.foldM (fun d a _ => f d a) init = m.keys.foldlM f init :=
DHashMap.Raw.Const.foldM_eq_foldlM_keys h.out
theorem fold_eq_foldl_keys (h : m.WF) {f : δ → α → δ} {init : δ} :
m.fold (fun d a _ => f d a) init = m.keys.foldl f init :=
DHashMap.Raw.Const.fold_eq_foldl_keys h.out
theorem forM_eq_forM_keys [Monad m'] [LawfulMonad m'] (h : m.WF) {f : α → m' PUnit} :
m.forM (fun a _ => f a) = m.keys.forM f :=
DHashMap.Raw.Const.forM_eq_forM_keys h.out
theorem forIn_eq_forIn_keys [Monad m'] [LawfulMonad m'] (h : m.WF)
{f : α → δ → m' (ForInStep δ)} {init : δ} :
m.forIn (fun a _ d => f a d) init = ForIn.forIn m.keys init f :=
DHashMap.Raw.Const.forIn_eq_forIn_keys h.out
end monadic
@[simp]
theorem insertMany_nil (h : m.WF) :
insertMany m [] = m :=

View file

@ -170,19 +170,6 @@ 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. -/
/-- Removes all elements from the hash set for which the given function returns `false`. -/
@[inline] def filter (f : α → Bool) (m : HashSet α) : HashSet α :=
⟨m.inner.filter fun a _ => f a⟩
/-- Partition a hashset into two hashsets based on a predicate. -/
@[inline] def partition (f : α → Bool) (m : HashSet α) : HashSet α × HashSet α :=
let ⟨l, r⟩ := m.inner.partition fun a _ => f a
⟨⟨l⟩, ⟨r⟩⟩
/--
Monadically computes a value by folding the given function over the elements in the hash set in some
order.
@ -212,6 +199,19 @@ instance [BEq α] [Hashable α] {m : Type v → Type v} : ForM m (HashSet α) α
instance [BEq α] [Hashable α] {m : Type v → Type v} : ForIn m (HashSet α) α where
forIn m init f := m.forIn f init
section Unverified
/-! We currently do not provide lemmas for the functions below. -/
/-- Removes all elements from the hash set for which the given function returns `false`. -/
@[inline] def filter (f : α → Bool) (m : HashSet α) : HashSet α :=
⟨m.inner.filter fun a _ => f a⟩
/-- Partition a hashset into two hashsets based on a predicate. -/
@[inline] def partition (f : α → Bool) (m : HashSet α) : HashSet α × HashSet α :=
let ⟨l, r⟩ := m.inner.partition fun a _ => f a
⟨⟨l⟩, ⟨r⟩⟩
/-- Check if all elements satisfy the predicate, short-circuiting if a predicate fails. -/
@[inline] def all (m : HashSet α) (p : α → Bool) : Bool := Id.run do
for a in m do

View file

@ -374,6 +374,39 @@ theorem distinct_toList [EquivBEq α] [LawfulHashable α]:
m.toList.Pairwise (fun a b => (a == b) = false) :=
HashMap.distinct_keys
section monadic
variable {δ : Type v} {m' : Type v → Type v}
theorem foldM_eq_foldlM_toList [Monad m'] [LawfulMonad m']
{f : δ → α → m' δ} {init : δ} :
m.foldM f init = m.toList.foldlM f init :=
HashMap.foldM_eq_foldlM_keys
theorem fold_eq_foldl_toList {f : δ → α → δ} {init : δ} :
m.fold f init = m.toList.foldl f init :=
HashMap.fold_eq_foldl_keys
@[simp]
theorem forM_eq_forM [Monad m'] [LawfulMonad m'] {f : α → m' PUnit} :
m.forM f = ForM.forM m f := rfl
theorem forM_eq_forM_toList [Monad m'] [LawfulMonad m'] {f : α → m' PUnit} :
ForM.forM m f = ForM.forM m.toList f :=
HashMap.forM_eq_forM_keys
@[simp]
theorem forIn_eq_forIn [Monad m'] [LawfulMonad m']
{f : α → δ → m' (ForInStep δ)} {init : δ} :
m.forIn f init = ForIn.forIn m init f := rfl
theorem forIn_eq_forIn_toList [Monad m'] [LawfulMonad m']
{f : α → δ → m' (ForInStep δ)} {init : δ} :
ForIn.forIn m init f = ForIn.forIn m.toList init f :=
HashMap.forIn_eq_forIn_keys
end monadic
@[simp]
theorem insertMany_nil :
insertMany m [] = m :=

View file

@ -173,14 +173,6 @@ 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. -/
/-- Removes all elements from the hash set for which the given function returns `false`. -/
@[inline] def filter [BEq α] [Hashable α] (f : α → Bool) (m : Raw α) : Raw α :=
⟨m.inner.filter fun a _ => f a⟩
/--
Monadically computes a value by folding the given function over the elements in the hash set in some
order.
@ -208,6 +200,14 @@ instance {m : Type v → Type v} : ForM m (Raw α) α where
instance {m : Type v → Type v} : ForIn m (Raw α) α where
forIn m init f := m.forIn f init
section Unverified
/-! We currently do not provide lemmas for the functions below. -/
/-- Removes all elements from the hash set for which the given function returns `false`. -/
@[inline] def filter [BEq α] [Hashable α] (f : α → Bool) (m : Raw α) : Raw α :=
⟨m.inner.filter fun a _ => f a⟩
/-- Check if all elements satisfy the predicate, short-circuiting if a predicate fails. -/
@[inline] def all (m : Raw α) (p : α → Bool) : Bool := Id.run do
for a in m do

View file

@ -390,6 +390,41 @@ theorem distinct_toList [EquivBEq α] [LawfulHashable α] (h : m.WF) :
m.toList.Pairwise (fun a b => (a == b) = false) :=
HashMap.Raw.distinct_keys h.1
section monadic
variable {m : Raw α} {δ : Type v} {m' : Type v → Type v}
theorem foldM_eq_foldlM_toList [Monad m'] [LawfulMonad m'] (h : m.WF)
{f : δ → α → m' δ} {init : δ} :
m.foldM f init = m.toList.foldlM f init :=
HashMap.Raw.foldM_eq_foldlM_keys h.out
theorem fold_eq_foldl_toList (h : m.WF) {f : δ → α → δ} {init : δ} :
m.fold f init = m.toList.foldl f init :=
HashMap.Raw.fold_eq_foldl_keys h.out
omit [BEq α] [Hashable α] in
@[simp]
theorem forM_eq_forM [Monad m'] [LawfulMonad m'] {f : α → m' PUnit} :
m.forM f = ForM.forM m f := rfl
theorem forM_eq_forM_toList [Monad m'] [LawfulMonad m'] (h : m.WF) {f : α → m' PUnit} :
ForM.forM m f = ForM.forM m.toList f :=
HashMap.Raw.forM_eq_forM_keys h.out
omit [BEq α] [Hashable α] in
@[simp]
theorem forIn_eq_forIn [Monad m'] [LawfulMonad m']
{f : α → δ → m' (ForInStep δ)} {init : δ} :
m.forIn f init = ForIn.forIn m init f := rfl
theorem forIn_eq_forIn_toList [Monad m'] [LawfulMonad m'] (h : m.WF)
{f : α → δ → m' (ForInStep δ)} {init : δ} :
ForIn.forIn m init f = ForIn.forIn m.toList init f :=
HashMap.Raw.forIn_eq_forIn_keys h.out
end monadic
@[simp]
theorem insertMany_nil (h : m.WF) :
insertMany m [] = m :=

View file

@ -8,6 +8,7 @@ import Init.Data.BEq
import Init.Data.Nat.Simproc
import Init.Data.List.Perm
import Init.Data.List.Find
import Init.Data.List.Monadic
import Std.Classes.Ord
import Std.Data.Internal.List.Defs
@ -2088,6 +2089,107 @@ theorem pairwise_fst_eq_false_map_toProd [BEq α] {β : Type v}
simp [List.pairwise_map]
assumption
theorem foldlM_eq_foldlM_toProd {β : Type v} {δ : Type w} {m' : Type w → Type w} [Monad m']
[LawfulMonad m'] {l : List ((_ : α) × β)} {f : δ → (a : α) → β → m' δ} {init : δ} :
l.foldlM (fun a b => f a b.fst b.snd) init =
(l.map fun x => (x.1, x.2)).foldlM (fun a b => f a b.fst b.snd) init := by
induction l generalizing init with
| nil => simp
| cons hd tl ih => simp [ih]
theorem foldl_eq_foldl_toProd {β : Type v} {δ : Type w}
{l : List ((_ : α) × β)} {f : δ → (a : α) → β → δ} {init : δ} :
l.foldl (fun a b => f a b.fst b.snd) init =
(l.map fun x => (x.1, x.2)).foldl (fun a b => f a b.fst b.snd) init := by
induction l generalizing init with
| nil => simp
| cons hd tl ih => simp [ih]
theorem foldrM_eq_foldrM_toProd {β : Type v} {δ : Type w} {m' : Type w → Type w} [Monad m']
[LawfulMonad m'] {l : List ((_ : α) × β)} {f : δ → (a : α) → β → m' δ} {init : δ} :
l.foldrM (fun a b => f b a.1 a.2) init =
(l.map fun x => (x.1, x.2)).foldrM (fun a b => f b a.1 a.2) init := by
induction l generalizing init with
| nil => simp
| cons hd tl ih => simp [ih]
theorem foldr_eq_foldr_toProd {β : Type v} {δ : Type w}
{l : List ((_ : α) × β)} {f : δ → (a : α) → β → δ} {init : δ} :
l.foldr (fun a b => f b a.1 a.2) init =
(l.map fun x => (x.1, x.2)).foldr (fun a b => f b a.1 a.2) init := by
induction l generalizing init with
| nil => simp
| cons hd tl ih => simp [ih]
theorem forM_eq_forM_toProd {β : Type v} {m' : Type w → Type w} [Monad m']
[LawfulMonad m'] {l : List ((_ : α) × β)} {f : (a : α) → β → m' PUnit} :
forM l (fun a => f a.1 a.2) = forM (l.map (fun x => (x.1, x.2))) fun a => f a.1 a.2 := by
cases l with
| nil => simp
| cons hd tl => simp
theorem forIn_eq_forIn_toProd {β : Type v} {δ : Type w} {m' : Type w → Type w} [Monad m']
[LawfulMonad m'] {l : List ((_ : α) × β)} {f : (a : α) → β → δ → m' (ForInStep δ)} {init : δ} :
ForIn.forIn l init (fun a d => f a.1 a.2 d) =
ForIn.forIn (l.map (fun x => (x.1, x.2))) init fun a d => f a.1 a.2 d := by
cases l with
| nil => simp
| cons hd tl => simp
theorem foldlM_eq_foldlM_keys {δ : Type w} {m' : Type w → Type w} [Monad m'] [LawfulMonad m']
{l : List ((_ : α) × Unit)} {f : δ → α → m' δ} {init : δ} :
l.foldlM (fun a b => f a b.1) init = (keys l).foldlM f init := by
induction l generalizing init with
| nil => simp
| cons hd tl ih =>
simp only [List.foldlM_cons, keys]
congr
simp [ih]
theorem foldl_eq_foldl_keys {δ : Type w}
{l : List ((_ : α) × Unit)} {f : δ → α → δ} {init : δ} :
l.foldl (fun a b => f a b.1) init = (keys l).foldl f init := by
induction l generalizing init with
| nil => simp
| cons hd tl ih => simp [List.foldlM_cons, keys, ih]
theorem foldrM_eq_foldrM_keys {δ : Type w} {m' : Type w → Type w} [Monad m'] [LawfulMonad m']
{l : List ((_ : α) × Unit)} {f : δ → α → m' δ} {init : δ} :
l.foldrM (fun a b => f b a.1) init = (keys l).foldrM (fun a b => f b a) init := by
induction l generalizing init with
| nil => simp
| cons hd tl ih =>
simp [keys, ih]
theorem foldr_eq_foldr_keys {δ : Type w}
{l : List ((_ : α) × Unit)} {f : δ → α → δ} {init : δ} :
l.foldr (fun a b => f b a.1) init = (keys l).foldr (fun a b => f b a) init := by
induction l generalizing init with
| nil => simp
| cons hd tl ih => simp [keys, ih]
theorem forM_eq_forM_keys {m' : Type w → Type w} [Monad m'] [LawfulMonad m']
{l : List ((_ : α) × Unit)} {f : α → m' PUnit} :
l.forM (fun a => f a.1) = (keys l).forM f := by
induction l with
| nil => simp
| cons hd tl ih =>
simp only [List.forM_eq_forM, List.forM_cons, keys]
congr
funext x
apply ih
theorem forIn_eq_forIn_keys {δ : Type w} {m' : Type w → Type w} [Monad m'] [LawfulMonad m']
{f : α → δ → m' (ForInStep δ)} {init : δ} {l : List ((_ : α) × Unit)} :
ForIn.forIn l init (fun a d => f a.fst d) = ForIn.forIn (keys l) init f := by
induction l generalizing init with
| nil => simp
| cons hd tl ih =>
simp [keys]
congr
funext x
cases x <;> simp[ih]
/-- Internal implementation detail of the hash map -/
def insertList [BEq α] (l toInsert : List ((a : α) × β a)) : List ((a : α) × β a) :=
match toInsert with