This PR deprecates various duplicated definitions, detected in [#mathlib4 > duplicate declarations @ 💬](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/duplicate.20declarations/near/547434277)
8118 lines
381 KiB
Text
8118 lines
381 KiB
Text
/-
|
||
Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Markus Himmel
|
||
-/
|
||
module
|
||
|
||
prelude
|
||
public import Init.Data.Option.Attach
|
||
public import Init.Data.List.Perm
|
||
public import Std.Data.Internal.List.Defs
|
||
import all Std.Data.Internal.List.Defs
|
||
public import Init.Data.Order.Ord
|
||
import Init.Data.Subtype.Order
|
||
|
||
public section
|
||
|
||
/-!
|
||
This is an internal implementation file of the hash map. Users of the hash map should not rely on
|
||
the contents of this file.
|
||
|
||
File contents: Verification of associative lists
|
||
-/
|
||
|
||
set_option linter.missingDocs true
|
||
set_option autoImplicit false
|
||
|
||
universe u v w w'
|
||
|
||
variable {α : Type u} {β : α → Type v} {γ : α → Type w}
|
||
|
||
open List (Perm Sublist pairwise_cons erase_sublist filter_sublist)
|
||
|
||
namespace Std.Internal.List
|
||
|
||
attribute [-simp] List.isEmpty_eq_false_iff
|
||
|
||
@[elab_as_elim]
|
||
theorem assoc_induction {motive : List ((a : α) × β a) → Prop} (nil : motive [])
|
||
(cons : (k : α) → (v : β k) → (tail : List ((a : α) × β a)) →
|
||
motive tail → motive (⟨k, v⟩ :: tail)) :
|
||
(t : List ((a : α) × β a)) → motive t
|
||
| [] => nil
|
||
| ⟨_, _⟩ :: _ => cons _ _ _ (assoc_induction nil cons _)
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def getEntry? [BEq α] (a : α) : List ((a : α) × β a) → Option ((a : α) × β a)
|
||
| [] => none
|
||
| ⟨k, v⟩ :: l => bif k == a then some ⟨k, v⟩ else getEntry? a l
|
||
|
||
@[simp] theorem getEntry?_nil [BEq α] {a : α} :
|
||
getEntry? a ([] : List ((a : α) × β a)) = none := (rfl)
|
||
theorem getEntry?_cons [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} :
|
||
getEntry? a (⟨k, v⟩ :: l) = bif k == a then some ⟨k, v⟩ else getEntry? a l := (rfl)
|
||
|
||
theorem getEntry?_eq_find [BEq α] {k : α} {l : List ((a : α) × β a)} :
|
||
getEntry? k l = l.find? (·.1 == k) := by
|
||
induction l using assoc_induction with
|
||
| nil => simp
|
||
| cons k' v t ih => cases h : k' == k <;> simp_all [getEntry?_cons]
|
||
|
||
theorem getEntry?_cons_of_true [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} (h : k == a) :
|
||
getEntry? a (⟨k, v⟩ :: l) = some ⟨k, v⟩ := by
|
||
simp [getEntry?, h]
|
||
|
||
theorem getEntry?_cons_of_false [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k}
|
||
(h : (k == a) = false) : getEntry? a (⟨k, v⟩ :: l) = getEntry? a l := by
|
||
simp [getEntry?, h]
|
||
|
||
@[simp]
|
||
theorem getEntry?_cons_self [BEq α] [ReflBEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
getEntry? k (⟨k, v⟩ :: l) = some ⟨k, v⟩ :=
|
||
getEntry?_cons_of_true BEq.rfl
|
||
|
||
theorem beq_of_getEntry?_eq_some [BEq α] {l : List ((a : α) × β a)} {a : α} {p : (a : α) × β a}
|
||
(h : getEntry? a l = some p) : p.1 == a := by
|
||
induction l using assoc_induction
|
||
· simp at h
|
||
next k' v' t ih =>
|
||
cases h' : k' == a
|
||
· rw [getEntry?_cons_of_false h'] at h
|
||
exact ih h
|
||
· rw [getEntry?_cons_of_true h', Option.some.injEq] at h
|
||
obtain rfl := congrArg Sigma.fst h
|
||
exact h'
|
||
|
||
theorem getEntry?_congr [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {a b : α}
|
||
(h : a == b) : getEntry? a l = getEntry? b l := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k v l ih =>
|
||
cases h' : k == a
|
||
· have h₂ : (k == b) = false := BEq.neq_of_neq_of_beq h' h
|
||
rw [getEntry?_cons_of_false h', getEntry?_cons_of_false h₂, ih]
|
||
· rw [getEntry?_cons_of_true h', getEntry?_cons_of_true (BEq.trans h' h)]
|
||
|
||
theorem keys_eq_map {l : List ((a : α) × β a)} :
|
||
keys l = l.map (·.1) := by
|
||
induction l with
|
||
| nil => rfl
|
||
| cons => simp [keys, *]
|
||
|
||
theorem getEntry?_eq_some_iff [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {e} {k}
|
||
(hd : DistinctKeys l) :
|
||
getEntry? k l = some e ↔ k == e.1 ∧ e ∈ l := by
|
||
replace hd := hd.distinct
|
||
induction l using assoc_induction with
|
||
| nil => simp
|
||
| cons lk lv tail ih =>
|
||
simp only [getEntry?_cons, cond_eq_ite, List.mem_cons]
|
||
split
|
||
· rename_i hlkk
|
||
simp only [Option.some.injEq]
|
||
replace hd := pairwise_cons.mp hd
|
||
refine ⟨fun heq => ⟨(congrArg (Sigma.fst) heq.symm) ▸ BEq.symm hlkk, Or.inl heq.symm⟩, ?_⟩
|
||
rintro ⟨hbeq, ⟨rfl|h⟩⟩
|
||
· rfl
|
||
· exfalso
|
||
rename_i h
|
||
have := hd.1 _ <| keys_eq_map ▸ List.mem_map_of_mem h
|
||
simp_all [BEq.trans hlkk hbeq]
|
||
· rename_i h
|
||
replace h := h.imp BEq.symm
|
||
simp only [ih hd.tail, Sigma.ext_iff, and_congr_right_iff, iff_or_self, and_imp]
|
||
intros; simp_all
|
||
|
||
theorem mem_iff_getEntry?_eq_some [BEq α] [EquivBEq α] {l : List ((a : α) × β a)}
|
||
{p : (a : α) × β a} (h : DistinctKeys l) : p ∈ l ↔ getEntry? p.1 l = some p := by
|
||
simp [getEntry?_eq_some_iff h]
|
||
|
||
theorem isEmpty_eq_false_iff_exists_isSome_getEntry? [BEq α] [ReflBEq α] :
|
||
{l : List ((a : α) × β a)} → l.isEmpty = false ↔ ∃ a, (getEntry? a l).isSome
|
||
| [] => by simp
|
||
| (⟨k, v⟩::l) => by simpa using ⟨k, by simp⟩
|
||
|
||
theorem isEmpty_iff_forall_isSome_getEntry? [BEq α] [ReflBEq α] :
|
||
{l : List ((a : α) × β a)} → l.isEmpty ↔ ∀ a, (getEntry? a l).isSome = false
|
||
| [] => by simp
|
||
| (⟨k, v⟩::l) => ⟨by simp, fun h => have := h k; by simp at this⟩
|
||
|
||
section
|
||
|
||
variable {β : Type v}
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
@[expose] def getValue? [BEq α] (a : α) : List ((_ : α) × β) → Option β
|
||
| [] => none
|
||
| ⟨k, v⟩ :: l => bif k == a then some v else getValue? a l
|
||
|
||
@[simp] theorem getValue?_nil [BEq α] {a : α} : getValue? a ([] : List ((_ : α) × β)) = none := rfl
|
||
theorem getValue?_cons [BEq α] {l : List ((_ : α) × β)} {k a : α} {v : β} :
|
||
getValue? a (⟨k, v⟩ :: l) = bif k == a then some v else getValue? a l := rfl
|
||
|
||
theorem getValue?_cons_of_true [BEq α] {l : List ((_ : α) × β)} {k a : α} {v : β} (h : k == a) :
|
||
getValue? a (⟨k, v⟩ :: l) = some v := by
|
||
simp [getValue?, h]
|
||
|
||
theorem getValue?_cons_of_false [BEq α] {l : List ((_ : α) × β)} {k a : α} {v : β}
|
||
(h : (k == a) = false) : getValue? a (⟨k, v⟩ :: l) = getValue? a l := by
|
||
simp [getValue?, h]
|
||
|
||
@[simp]
|
||
theorem getValue?_cons_self [BEq α] [ReflBEq α] {l : List ((_ : α) × β)} {k : α} {v : β} :
|
||
getValue? k (⟨k, v⟩ :: l) = some v :=
|
||
getValue?_cons_of_true BEq.rfl
|
||
|
||
theorem getValue?_eq_getEntry? [BEq α] {l : List ((_ : α) × β)} {a : α} :
|
||
getValue? a l = (getEntry? a l).map (·.2) := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k v l ih =>
|
||
cases h : k == a
|
||
· rw [getEntry?_cons_of_false h, getValue?_cons_of_false h, ih]
|
||
· rw [getEntry?_cons_of_true h, getValue?_cons_of_true h, Option.map_some]
|
||
|
||
theorem getValue?_congr [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)} {a b : α}
|
||
(h : a == b) : getValue? a l = getValue? b l := by
|
||
simp [getValue?_eq_getEntry?, getEntry?_congr h]
|
||
|
||
theorem isEmpty_eq_false_iff_exists_isSome_getValue? [BEq α] [ReflBEq α] {l : List ((_ : α) × β)} :
|
||
l.isEmpty = false ↔ ∃ a, (getValue? a l).isSome := by
|
||
simp [isEmpty_eq_false_iff_exists_isSome_getEntry?, getValue?_eq_getEntry?]
|
||
|
||
end
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
@[expose] def getValueCast? [BEq α] [LawfulBEq α] (a : α) : List ((a : α) × β a) → Option (β a)
|
||
| [] => none
|
||
| ⟨k, v⟩ :: l => if h : k == a then some (cast (congrArg β (eq_of_beq h)) v)
|
||
else getValueCast? a l
|
||
|
||
@[simp] theorem getValueCast?_nil [BEq α] [LawfulBEq α] {a : α} :
|
||
getValueCast? a ([] : List ((a : α) × β a)) = none := rfl
|
||
theorem getValueCast?_cons [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} :
|
||
getValueCast? a (⟨k, v⟩ :: l) = if h : k == a then some (cast (congrArg β (eq_of_beq h)) v)
|
||
else getValueCast? a l := rfl
|
||
|
||
theorem getValueCast?_cons_of_true [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} (h : k == a) :
|
||
getValueCast? a (⟨k, v⟩ :: l) = some (cast (congrArg β (eq_of_beq h)) v) := by
|
||
simp [getValueCast?, h]
|
||
|
||
theorem getValueCast?_cons_of_false [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} (h : (k == a) = false) : getValueCast? a (⟨k, v⟩ :: l) = getValueCast? a l := by
|
||
simp [getValueCast?, h]
|
||
|
||
@[simp]
|
||
theorem getValueCast?_cons_self [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
getValueCast? k (⟨k, v⟩ :: l) = some v := by
|
||
rw [getValueCast?_cons_of_true BEq.rfl, cast_eq]
|
||
|
||
theorem getValue?_eq_getValueCast? [BEq α] [LawfulBEq α] {β : Type v} {l : List ((_ : α) × β)}
|
||
{a : α} : getValue? a l = getValueCast? a l := by
|
||
induction l using assoc_induction <;> simp_all [getValueCast?_cons, getValue?_cons]
|
||
|
||
section
|
||
|
||
variable {β : Type v}
|
||
|
||
/-- This is a strange dependent version of `Option.map` in which the mapping function is allowed to
|
||
"know" about the option that is being mapped. This happens to be useful in this file (see
|
||
`getValueCast_eq_getEntry?`), but we do not want it to leak out of the file. -/
|
||
private def Option.dmap : (o : Option α) → (f : (a : α) → (o = some a) → β) → Option β
|
||
| none, _ => none
|
||
| some a, f => some (f a rfl)
|
||
|
||
@[simp] private theorem Option.dmap_none (f : (a : α) → (none = some a) → β) :
|
||
Option.dmap none f = none := rfl
|
||
|
||
@[simp] private theorem Option.dmap_some (a : α) (f : (a' : α) → (some a = some a') → β) :
|
||
Option.dmap (some a) f = some (f a rfl) := rfl
|
||
|
||
@[congr] private theorem Option.dmap_congr {o o' : Option α} (ho : o = o')
|
||
{f : (a : α) → o = some a → β} {f' : (a : α) → o' = some a → β}
|
||
(hf : ∀ a h, f a (ho.trans h) = f' a h) :
|
||
Option.dmap o f = Option.dmap o' f' := by
|
||
cases ho
|
||
cases o <;> simp only [hf, Option.dmap]
|
||
|
||
@[simp]
|
||
private theorem Option.isSome_dmap {o : Option α} {f : (a : α) → (o = some a) → β} :
|
||
(Option.dmap o f).isSome = o.isSome := by
|
||
cases o <;> rfl
|
||
|
||
private theorem Option.dmap_eq_some {o : Option α} {f : (a : α) → (o = some a) → β} (b : β) :
|
||
(Option.dmap o f) = some b ↔ ∃ (a : α) (h : o = some a), f a h = b := by
|
||
cases o with
|
||
| none => simp
|
||
| some a =>
|
||
simp only [dmap_some, Option.some.injEq]
|
||
exact ⟨by rintro rfl; exact ⟨a, rfl, rfl⟩, by rintro ⟨_, rfl, h⟩; exact h⟩
|
||
|
||
end
|
||
|
||
private theorem getValueCast?_eq_getEntry? [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α} :
|
||
getValueCast? a l = Option.dmap (getEntry? a l)
|
||
(fun p h => cast (congrArg β (eq_of_beq (beq_of_getEntry?_eq_some h))) p.2) := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k v t ih =>
|
||
cases h : k == a
|
||
· simp only [getValueCast?_cons_of_false h, ih, getEntry?_cons_of_false h]
|
||
· simp only [getValueCast?_cons_of_true h, getEntry?_cons_of_true h, Option.dmap_some]
|
||
|
||
theorem isSome_getValueCast?_eq_isSome_getEntry? [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)}
|
||
{a : α} : (getValueCast? a l).isSome = (getEntry? a l).isSome := by
|
||
rw [getValueCast?_eq_getEntry?, Option.isSome_dmap]
|
||
|
||
theorem isEmpty_eq_false_iff_exists_isSome_getValueCast? [BEq α] [LawfulBEq α]
|
||
{l : List ((a : α) × β a)} : l.isEmpty = false ↔ ∃ a, (getValueCast? a l).isSome := by
|
||
simp [isEmpty_eq_false_iff_exists_isSome_getEntry?, isSome_getValueCast?_eq_isSome_getEntry?]
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def containsKey [BEq α] (a : α) : List ((a : α) × β a) → Bool
|
||
| [] => false
|
||
| ⟨k, _⟩ :: l => k == a || containsKey a l
|
||
|
||
@[simp] theorem containsKey_nil [BEq α] {a : α} :
|
||
containsKey a ([] : List ((a : α) × β a)) = false := (rfl)
|
||
@[simp] theorem containsKey_cons [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} :
|
||
containsKey a (⟨k, v⟩ :: l) = (k == a || containsKey a l) := (rfl)
|
||
|
||
theorem containsKey_cons_eq_false [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} :
|
||
(containsKey a (⟨k, v⟩ :: l) = false) ↔ ((k == a) = false) ∧ (containsKey a l = false) := by
|
||
simp [containsKey_cons]
|
||
|
||
theorem containsKey_cons_eq_true [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} :
|
||
(containsKey a (⟨k, v⟩ :: l)) ↔ (k == a) ∨ (containsKey a l) := by
|
||
simp [containsKey_cons]
|
||
|
||
theorem containsKey_cons_of_beq [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k}
|
||
(h : k == a) : containsKey a (⟨k, v⟩ :: l) := containsKey_cons_eq_true.2 <| Or.inl h
|
||
|
||
@[simp]
|
||
theorem containsKey_cons_self [BEq α] [ReflBEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
containsKey k (⟨k, v⟩ :: l) := containsKey_cons_of_beq BEq.rfl
|
||
|
||
theorem containsKey_cons_of_containsKey [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k}
|
||
(h : containsKey a l) : containsKey a (⟨k, v⟩ :: l) := containsKey_cons_eq_true.2 <| Or.inr h
|
||
|
||
theorem containsKey_of_containsKey_cons [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k}
|
||
(h₁ : containsKey a (⟨k, v⟩ :: l)) (h₂ : (k == a) = false) : containsKey a l := by
|
||
rcases (containsKey_cons_eq_true.1 h₁) with (h|h)
|
||
· exact False.elim (Bool.eq_false_iff.1 h₂ h)
|
||
· exact h
|
||
|
||
theorem containsKey_eq_isSome_getEntry? [BEq α] {l : List ((a : α) × β a)} {a : α} :
|
||
containsKey a l = (getEntry? a l).isSome := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k v l ih =>
|
||
cases h : k == a
|
||
· simp [getEntry?_cons_of_false h, h, ih]
|
||
· simp [getEntry?_cons_of_true h, h]
|
||
|
||
theorem containsKey_eq_true_iff_exists_mem [BEq α] {l : List ((a : α) × β a)} {a : α} :
|
||
containsKey a l = true ↔ ∃ p ∈ l, p.1 == a := by
|
||
induction l using assoc_induction <;> simp_all
|
||
|
||
theorem containsKey_of_mem [BEq α] [ReflBEq α] {l : List ((a : α) × β a)} {p : (a : α) × β a}
|
||
(hp : p ∈ l) : containsKey p.1 l :=
|
||
containsKey_eq_true_iff_exists_mem.2 ⟨p, ⟨hp, BEq.rfl⟩⟩
|
||
|
||
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]
|
||
|
||
@[simp] theorem keys_nil : keys ([] : List ((a : α) × β a)) = [] := (rfl)
|
||
@[simp] theorem keys_cons {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
keys (⟨k, v⟩ :: l) = k :: keys l := (rfl)
|
||
|
||
theorem length_keys_eq_length (l : List ((a : α) × β a)) : (keys l).length = l.length := by
|
||
induction l using assoc_induction <;> simp_all
|
||
|
||
theorem isEmpty_keys_eq_isEmpty (l : List ((a : α) × β a)) : (keys l).isEmpty = l.isEmpty := by
|
||
induction l using assoc_induction <;> simp_all
|
||
|
||
theorem containsKey_eq_keys_contains [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{a : α} : containsKey a l = (keys l).contains a := by
|
||
induction l using assoc_induction
|
||
· rfl
|
||
next k _ l ih => simp [ih, BEq.comm]
|
||
|
||
theorem containsKey_of_mem_keys [BEq α] [EquivBEq α] {l : List ((a : α) × β a)}
|
||
{a : α} (h : a ∈ keys l) : containsKey a l :=
|
||
containsKey_eq_keys_contains.trans (List.elem_eq_true_of_mem h)
|
||
|
||
@[simp]
|
||
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)}
|
||
(h : Perm (keys l') (keys l)) : DistinctKeys l → DistinctKeys l'
|
||
| ⟨h'⟩ => ⟨h'.perm h.symm BEq.symm_false⟩
|
||
|
||
theorem DistinctKeys.perm [BEq α] [PartialEquivBEq α] {l l' : List ((a : α) × β a)}
|
||
(h : Perm l' l) : DistinctKeys l → DistinctKeys l' :=
|
||
DistinctKeys.perm_keys (by simpa only [keys_eq_map] using h.map _)
|
||
|
||
theorem DistinctKeys.congr [BEq α] [PartialEquivBEq α] {l l' : List ((a : α) × β a)}
|
||
(h : Perm l l') : DistinctKeys l ↔ DistinctKeys l' :=
|
||
⟨fun h' => h'.perm h.symm, fun h' => h'.perm h⟩
|
||
|
||
theorem distinctKeys_of_sublist_keys [BEq α] {l : List ((a : α) × β a)} {l' : List ((a : α) × γ a)}
|
||
(h : Sublist (keys l') (keys l)) : DistinctKeys l → DistinctKeys l' :=
|
||
fun ⟨h'⟩ => ⟨h'.sublist h⟩
|
||
|
||
theorem distinctKeys_of_sublist [BEq α] {l l' : List ((a : α) × β a)} (h : Sublist l' l) :
|
||
DistinctKeys l → DistinctKeys l' :=
|
||
distinctKeys_of_sublist_keys (by simpa only [keys_eq_map] using h.map _)
|
||
|
||
theorem DistinctKeys.of_keys_eq [BEq α] {l : List ((a : α) × β a)} {l' : List ((a : α) × γ a)}
|
||
(h : keys l = keys l') : DistinctKeys l → DistinctKeys l' :=
|
||
distinctKeys_of_sublist_keys (h ▸ Sublist.refl _)
|
||
|
||
theorem containsKey_iff_exists [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {a : α} :
|
||
containsKey a l ↔ ∃ a' ∈ keys l, a == a' := by
|
||
rw [containsKey_eq_keys_contains, List.contains_iff_exists_mem_beq]
|
||
|
||
theorem containsKey_eq_false_iff_forall_mem_keys [BEq α] [PartialEquivBEq α]
|
||
{l : List ((a : α) × β a)} {a : α} :
|
||
(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
|
||
refine ⟨fun ⟨h⟩ => ?_, fun ⟨⟨h₁⟩, h₂⟩ => ⟨?_⟩⟩
|
||
· rw [keys_cons, pairwise_cons] at h
|
||
exact ⟨⟨h.2⟩, containsKey_eq_false_iff_forall_mem_keys.2 h.1⟩
|
||
· rw [keys_cons, pairwise_cons, ← containsKey_eq_false_iff_forall_mem_keys]
|
||
exact ⟨h₂, h₁⟩
|
||
|
||
theorem DistinctKeys.tail [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
DistinctKeys (⟨k, v⟩ :: l) → DistinctKeys l :=
|
||
fun h => (distinctKeys_cons_iff.mp h).1
|
||
|
||
theorem DistinctKeys.containsKey_eq_false [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{k : α} {v : β k} : DistinctKeys (⟨k, v⟩ :: l) → containsKey k l = false :=
|
||
fun h => (distinctKeys_cons_iff.mp h).2
|
||
|
||
theorem DistinctKeys.cons [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α} {v : β k}
|
||
(h : containsKey k l = false) : DistinctKeys l → DistinctKeys (⟨k, v⟩ :: l) :=
|
||
fun h' => distinctKeys_cons_iff.mpr ⟨h', h⟩
|
||
|
||
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
|
||
|
||
theorem isEmpty_eq_false_iff_exists_containsKey [BEq α] [ReflBEq α] {l : List ((a : α) × β a)} :
|
||
l.isEmpty = false ↔ ∃ a, containsKey a l := by
|
||
simp [isEmpty_eq_false_iff_exists_isSome_getEntry?, containsKey_eq_isSome_getEntry?]
|
||
|
||
theorem isEmpty_iff_forall_containsKey [BEq α] [ReflBEq α] {l : List ((a : α) × β a)} :
|
||
l.isEmpty ↔ ∀ a, containsKey a l = false := by
|
||
simp only [isEmpty_iff_forall_isSome_getEntry?, containsKey_eq_isSome_getEntry?]
|
||
|
||
@[simp]
|
||
theorem getEntry?_eq_none [BEq α] {l : List ((a : α) × β a)} {a : α} :
|
||
getEntry? a l = none ↔ containsKey a l = false := by
|
||
rw [← Option.not_isSome_iff_eq_none, Bool.not_eq_true, ← containsKey_eq_isSome_getEntry?]
|
||
|
||
@[simp]
|
||
theorem getValue?_eq_none {β : Type v} [BEq α] {l : List ((_ : α) × β)} {a : α} :
|
||
getValue? a l = none ↔ containsKey a l = false := by
|
||
rw [getValue?_eq_getEntry?, Option.map_eq_none_iff, getEntry?_eq_none]
|
||
|
||
theorem containsKey_eq_isSome_getValue? {β : Type v} [BEq α] {l : List ((_ : α) × β)} {a : α} :
|
||
containsKey a l = (getValue? a l).isSome := by
|
||
simp [containsKey_eq_isSome_getEntry?, getValue?_eq_getEntry?]
|
||
|
||
theorem containsKey_eq_isSome_getValueCast? [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)}
|
||
{a : α} : containsKey a l = (getValueCast? a l).isSome := by
|
||
simp [containsKey_eq_isSome_getEntry?, getValueCast?_eq_getEntry?]
|
||
|
||
theorem containsKey_of_getValueCast?_eq_some [BEq α] [LawfulBEq α]
|
||
{l : List ((a : α) × β a)} {a : α} {b : β a} (h : getValueCast? a l = some b) :
|
||
containsKey a l = true := by
|
||
simp [containsKey_eq_isSome_getValueCast?, h]
|
||
|
||
theorem containsKey_of_getValue_eq_some [BEq α] [LawfulBEq α] {β : Type v}
|
||
{l : List ((_ : α) × β)} {a : α} {b : β} (h : getValue? a l = some b) :
|
||
containsKey a l = true := by
|
||
simp [containsKey_eq_isSome_getValue?, h]
|
||
|
||
theorem getValueCast?_eq_none [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
(h : containsKey a l = false) : getValueCast? a l = none := by
|
||
rwa [← Option.not_isSome_iff_eq_none, ← containsKey_eq_isSome_getValueCast?, Bool.not_eq_true]
|
||
|
||
theorem containsKey_congr [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {a b : α}
|
||
(h : a == b) : containsKey a l = containsKey b l := by
|
||
simp [containsKey_eq_isSome_getEntry?, getEntry?_congr h]
|
||
|
||
theorem containsKey_of_beq [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {a b : α}
|
||
(hla : containsKey a l) (hab : a == b) : containsKey b l := by
|
||
rwa [← containsKey_congr hab]
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def getEntry [BEq α] (a : α) (l : List ((a : α) × β a)) (h : containsKey a l) : (a : α) × β a :=
|
||
(getEntry? a l).get <| containsKey_eq_isSome_getEntry?.symm.trans h
|
||
|
||
theorem getEntry?_eq_some_getEntry [BEq α] {l : List ((a : α) × β a)} {a : α}
|
||
(h : containsKey a l) : getEntry? a l = some (getEntry a l h) := by
|
||
simp [getEntry]
|
||
|
||
theorem getEntry_eq_of_getEntry?_eq_some [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k}
|
||
(h : getEntry? a l = some ⟨k, v⟩) {h'} : getEntry a l h' = ⟨k, v⟩ := by
|
||
simp [getEntry, h]
|
||
|
||
theorem getEntry_cons_of_beq [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} (h : k == a) :
|
||
getEntry a (⟨k, v⟩ :: l) (containsKey_cons_of_beq (v := v) h) = ⟨k, v⟩ := by
|
||
simp [getEntry, getEntry?_cons_of_true h]
|
||
|
||
@[simp]
|
||
theorem getEntry_cons_self [BEq α] [ReflBEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
getEntry k (⟨k, v⟩ :: l) containsKey_cons_self = ⟨k, v⟩ :=
|
||
getEntry_cons_of_beq BEq.rfl
|
||
|
||
theorem getEntry_cons_of_false [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k}
|
||
{h₁ : containsKey a (⟨k, v⟩ :: l)} (h₂ : (k == a) = false) : getEntry a (⟨k, v⟩ :: l) h₁ =
|
||
getEntry a l (containsKey_of_containsKey_cons (v := v) h₁ h₂) := by
|
||
simp [getEntry, getEntry?_cons_of_false h₂]
|
||
|
||
theorem getEntry_mem [BEq α] {l : List ((a : α) × β a)} {k : α} {h} :
|
||
getEntry k l h ∈ l := by
|
||
simp only [getEntry]
|
||
have h' := containsKey_eq_isSome_getEntry?.symm.trans h
|
||
change (getEntry? k l).get h' ∈ l
|
||
clear h
|
||
induction l using assoc_induction with
|
||
| nil => contradiction
|
||
| cons k v l ih =>
|
||
simp only [getEntry?_cons, cond_eq_ite]
|
||
split
|
||
· exact List.mem_cons_self
|
||
· simp only [List.mem_cons]
|
||
exact .inr (ih _)
|
||
|
||
theorem getEntry_of_mem [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {x : (a : α) × β a}
|
||
(h : x ∈ l) (hl : DistinctKeys l) :
|
||
getEntry x.fst l (containsKey_of_mem h) = x := by
|
||
induction h with
|
||
| head => simp [getEntry, getEntry?]
|
||
| @tail y l hm ih =>
|
||
rw [distinctKeys_cons_iff] at hl
|
||
have : (x.fst == y.fst) = false := by
|
||
false_or_by_contra
|
||
rename_i h
|
||
simp only [Bool.not_eq_false] at h
|
||
have := containsKey_of_mem hm
|
||
rw [containsKey_congr h] at this
|
||
simp [this] at hl
|
||
rw [getEntry_cons_of_false (BEq.symm_false this)]
|
||
apply ih (And.left hl)
|
||
|
||
section
|
||
|
||
variable {β : Type v}
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def getValue [BEq α] (a : α) (l : List ((_ : α) × β)) (h : containsKey a l) : β :=
|
||
(getValue? a l).get <| containsKey_eq_isSome_getValue?.symm.trans h
|
||
|
||
theorem getValue?_eq_some_getValue [BEq α] {l : List ((_ : α) × β)} {a : α} (h : containsKey a l) :
|
||
getValue? a l = some (getValue a l h) := by
|
||
simp [getValue]
|
||
|
||
theorem getValue?_eq_some_iff [BEq α] {l : List ((_ : α) × β)} {k : α} {v : β} :
|
||
getValue? k l = some v ↔ ∃ h : containsKey k l, getValue k l h = v := by
|
||
by_cases h : containsKey k l
|
||
· simp [h, getValue?_eq_some_getValue]
|
||
· simp [getValue?_eq_none.mpr (Bool.not_eq_true _ ▸ h), h]
|
||
|
||
theorem getValue_cons_of_beq [BEq α] {l : List ((_ : α) × β)} {k a : α} {v : β} (h : k == a) :
|
||
getValue a (⟨k, v⟩ :: l) (containsKey_cons_of_beq h) = v := by
|
||
simp [getValue, getValue?_cons_of_true h]
|
||
|
||
@[simp]
|
||
theorem getValue_cons_self [BEq α] [ReflBEq α] {l : List ((_ : α) × β)} {k : α} {v : β} :
|
||
getValue k (⟨k, v⟩ :: l) containsKey_cons_self = v :=
|
||
getValue_cons_of_beq BEq.rfl
|
||
|
||
theorem getValue_cons_of_false [BEq α] {l : List ((_ : α) × β)} {k a : α} {v : β}
|
||
{h₁ : containsKey a (⟨k, v⟩ :: l)} (h₂ : (k == a) = false) : getValue a (⟨k, v⟩ :: l) h₁ =
|
||
getValue a l (containsKey_of_containsKey_cons (k := k) (v := v) h₁ h₂) := by
|
||
simp [getValue, getValue?_cons_of_false h₂]
|
||
|
||
theorem getValue_cons [BEq α] {l : List ((_ : α) × β)} {k a : α} {v : β} {h} :
|
||
getValue a (⟨k, v⟩ :: l) h = if h' : k == a then v
|
||
else getValue a l (containsKey_of_containsKey_cons (k := k) h (Bool.eq_false_iff.2 h')) := by
|
||
rw [← Option.some_inj, ← getValue?_eq_some_getValue, getValue?_cons, apply_dite Option.some,
|
||
cond_eq_ite]
|
||
split
|
||
· rfl
|
||
· exact getValue?_eq_some_getValue _
|
||
|
||
theorem getValue_congr [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)} {a b : α} (hab : a == b)
|
||
{h} : getValue a l h = getValue b l ((containsKey_congr hab).symm.trans h) := by
|
||
rw [← Option.some_inj, ← getValue?_eq_some_getValue, ← getValue?_eq_some_getValue,
|
||
getValue?_congr hab]
|
||
|
||
theorem getValue_of_mem [BEq α] [EquivBEq α] {l : List ((_ : α) × β)} {x : (_ : α) × β}
|
||
(h : x ∈ l) {h'} (distinct : DistinctKeys l) :
|
||
getValue x.1 l h' = x.2 := by
|
||
induction h with
|
||
| head => rw [getValue_cons_of_beq]; simp
|
||
| @tail y l hmem ih =>
|
||
obtain (h|h) := containsKey_cons_eq_true.1 h'
|
||
· have := containsKey_of_mem hmem ▸ containsKey_congr h ▸ distinct.containsKey_eq_false
|
||
simp at this
|
||
· rw [getValue_cons_of_false, ih distinct.tail]
|
||
refine Bool.not_eq_true _ ▸ (fun hb => ?_)
|
||
simp [← containsKey_congr hb, distinct.containsKey_eq_false] at h
|
||
|
||
theorem getValue_eq_getEntry_snd [BEq α] [EquivBEq α] {l : List ((_ : α) × β)} {k : α} {h'} :
|
||
getValue k l h' = (getEntry k l h').snd := by
|
||
simp [getValue, getValue?_eq_getEntry?, getEntry, Option.get_map]
|
||
|
||
end
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def getValueCast [BEq α] [LawfulBEq α] (a : α) (l : List ((a : α) × β a)) (h : containsKey a l) :
|
||
β a :=
|
||
(getValueCast? a l).get <| containsKey_eq_isSome_getValueCast?.symm.trans h
|
||
|
||
theorem getValueCast?_eq_some_getValueCast [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
(h : containsKey a l) : getValueCast? a l = some (getValueCast a l h) := by
|
||
simp [getValueCast]
|
||
|
||
theorem getValueCast?_eq_some_iff [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
getValueCast? k l = some v ↔ ∃ h : containsKey k l, getValueCast k l h = v := by
|
||
by_cases h : containsKey k l
|
||
· simp [h, getValueCast?_eq_some_getValueCast]
|
||
· simp [getValueCast?_eq_none (Bool.not_eq_true _ ▸ h), h]
|
||
|
||
theorem getValueCast_cons [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k}
|
||
(h : containsKey a (⟨k, v⟩ :: l)) :
|
||
getValueCast a (⟨k, v⟩ :: l) h =
|
||
if h' : k == a then
|
||
cast (congrArg β (eq_of_beq h')) v
|
||
else
|
||
getValueCast a l (containsKey_of_containsKey_cons (k := k) h (Bool.eq_false_iff.2 h')) := by
|
||
rw [getValueCast, Option.get_congr getValueCast?_cons]
|
||
split <;> simp [getValueCast]
|
||
|
||
theorem getValueCast_mem [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
(h : containsKey a l) :
|
||
⟨a, getValueCast a l h⟩ ∈ l := by
|
||
induction l with
|
||
| nil => simp at h
|
||
| cons hd tl ih =>
|
||
simp only [List.mem_cons]
|
||
by_cases hd_a: hd.1 == a
|
||
· simp only [beq_iff_eq] at hd_a
|
||
rw [Sigma.ext_iff]
|
||
simp only [hd_a, getValueCast, getValueCast?, beq_self_eq_true, ↓reduceDIte, Option.get_some,
|
||
cast_heq, and_self, true_or]
|
||
· rw [getValueCast_cons]
|
||
simp only [hd_a, Bool.false_eq_true, ↓reduceDIte]
|
||
rw [containsKey_cons] at h
|
||
simp only [hd_a, Bool.false_or] at h
|
||
simp [ih h]
|
||
|
||
theorem getValueCast_of_mem [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {x : (a : α) × β a}
|
||
(h : x ∈ l) (distinct : DistinctKeys l) :
|
||
getValueCast x.1 l (containsKey_of_mem h) = x.2 := by
|
||
induction h with
|
||
| head => simp [getValueCast, getValueCast?]
|
||
| @tail y l hmem ih =>
|
||
obtain (h|h) := containsKey_cons_eq_true.1
|
||
(@containsKey_of_mem α β _ _ (y :: l) x (List.mem_of_mem_tail hmem))
|
||
· have := containsKey_of_mem hmem ▸ containsKey_congr h ▸ distinct.containsKey_eq_false
|
||
simp at this
|
||
· rw [getValueCast_cons]
|
||
split
|
||
· rename_i hxy
|
||
rw [distinctKeys_cons_iff] at distinct
|
||
simp [containsKey_congr hxy, h] at distinct
|
||
· simp [ih distinct.tail]
|
||
|
||
theorem getValue_eq_getValueCast {β : Type v} [BEq α] [LawfulBEq α] {l : List ((_ : α) × β)} {a : α}
|
||
{h} : getValue a l h = getValueCast a l h := by
|
||
induction l using assoc_induction
|
||
· simp at h
|
||
· simp_all [getValue_cons, getValueCast_cons]
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
@[expose] def getValueCastD [BEq α] [LawfulBEq α] (a : α) (l : List ((a : α) × β a)) (fallback : β a) : β a :=
|
||
(getValueCast? a l).getD fallback
|
||
|
||
@[simp]
|
||
theorem getValueCastD_nil [BEq α] [LawfulBEq α] {a : α} {fallback : β a} :
|
||
getValueCastD a ([] : List ((a : α) × β a)) fallback = fallback := (rfl)
|
||
|
||
theorem getValueCastD_eq_getValueCast? [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
{fallback : β a} : getValueCastD a l fallback = (getValueCast? a l).getD fallback := (rfl)
|
||
|
||
theorem getValueCastD_eq_fallback [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
{fallback : β a} (h : containsKey a l = false) : getValueCastD a l fallback = fallback := by
|
||
rw [containsKey_eq_isSome_getValueCast?, Bool.eq_false_iff, ne_eq,
|
||
Option.not_isSome_iff_eq_none] at h
|
||
rw [getValueCastD_eq_getValueCast?, h, Option.getD_none]
|
||
|
||
theorem getValueCast_eq_getValueCastD [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
{fallback : β a} (h : containsKey a l = true) :
|
||
getValueCast a l h = getValueCastD a l fallback := by
|
||
rw [getValueCastD_eq_getValueCast?, getValueCast, Option.get_eq_getD]
|
||
|
||
theorem getValueCast?_eq_some_getValueCastD [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
{fallback : β a} (h : containsKey a l = true) :
|
||
getValueCast? a l = some (getValueCastD a l fallback) := by
|
||
rw [getValueCast?_eq_some_getValueCast h, getValueCast_eq_getValueCastD]
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
@[expose] def getValueCast! [BEq α] [LawfulBEq α] (a : α) [Inhabited (β a)] (l : List ((a : α) × β a)) :
|
||
β a :=
|
||
(getValueCast? a l).get!
|
||
|
||
@[simp]
|
||
theorem getValueCast!_nil [BEq α] [LawfulBEq α] {a : α} [Inhabited (β a)] :
|
||
getValueCast! a ([] : List ((a : α) × β a)) = default := (rfl)
|
||
|
||
theorem getValueCast!_eq_getValueCast? [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
[Inhabited (β a)] : getValueCast! a l = (getValueCast? a l).get! := (rfl)
|
||
|
||
theorem getValueCast!_eq_default [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
[Inhabited (β a)] (h : containsKey a l = false) : getValueCast! a l = default := by
|
||
rw [containsKey_eq_isSome_getValueCast?, Bool.eq_false_iff, ne_eq,
|
||
Option.not_isSome_iff_eq_none] at h
|
||
rw [getValueCast!_eq_getValueCast?, h, Option.get!_none]
|
||
|
||
theorem getValueCast_eq_getValueCast! [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
[Inhabited (β a)] (h : containsKey a l = true) : getValueCast a l h = getValueCast! a l := by
|
||
rw [getValueCast!_eq_getValueCast?, getValueCast, Option.get_eq_get!]
|
||
|
||
theorem getValueCast?_eq_some_getValueCast! [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
[Inhabited (β a)] (h : containsKey a l = true) :
|
||
getValueCast? a l = some (getValueCast! a l) := by
|
||
rw [getValueCast?_eq_some_getValueCast h, getValueCast_eq_getValueCast!]
|
||
|
||
theorem getValueCast!_eq_getValueCastD_default [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)}
|
||
{a : α} [Inhabited (β a)] : getValueCast! a l = getValueCastD a l default := (rfl)
|
||
|
||
section
|
||
|
||
variable {β : Type v}
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
@[expose] def getValueD [BEq α] (a : α) (l : List ((_ : α) × β)) (fallback : β) : β :=
|
||
(getValue? a l).getD fallback
|
||
|
||
@[simp]
|
||
theorem getValueD_nil [BEq α] {a : α} {fallback : β} :
|
||
getValueD a ([] : List ((_ : α) × β)) fallback = fallback := (rfl)
|
||
|
||
theorem getValueD_eq_getValue? [BEq α] {l : List ((_ : α) × β)} {a : α} {fallback : β} :
|
||
getValueD a l fallback = (getValue? a l).getD fallback := (rfl)
|
||
|
||
theorem getValueD_eq_fallback [BEq α] {l : List ((_ : α) × β)} {a : α} {fallback : β}
|
||
(h : containsKey a l = false) : getValueD a l fallback = fallback := by
|
||
rw [containsKey_eq_isSome_getValue?, Bool.eq_false_iff, ne_eq, Option.not_isSome_iff_eq_none] at h
|
||
rw [getValueD_eq_getValue?, h, Option.getD_none]
|
||
|
||
theorem getValue_eq_getValueD [BEq α] {l : List ((_ : α) × β)} {a : α} {fallback : β}
|
||
(h : containsKey a l = true) : getValue a l h = getValueD a l fallback := by
|
||
rw [getValueD_eq_getValue?, getValue, Option.get_eq_getD]
|
||
|
||
theorem getValue?_eq_some_getValueD [BEq α] {l : List ((_ : α) × β)} {a : α} {fallback : β}
|
||
(h : containsKey a l = true) : getValue? a l = some (getValueD a l fallback) := by
|
||
rw [getValue?_eq_some_getValue h, getValue_eq_getValueD]
|
||
|
||
theorem getValueD_eq_getValueCastD [BEq α] [LawfulBEq α] {l : List ((_ : α) × β)} {a : α}
|
||
{fallback : β} : getValueD a l fallback = getValueCastD a l fallback := by
|
||
simp only [getValueD_eq_getValue?, getValueCastD_eq_getValueCast?, getValue?_eq_getValueCast?]
|
||
|
||
theorem getValueD_congr [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)} {a b : α}
|
||
{fallback : β} (hab : a == b) : getValueD a l fallback = getValueD b l fallback := by
|
||
simp only [getValueD_eq_getValue?, getValue?_congr hab]
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
@[expose] def getValue! [BEq α] [Inhabited β] (a : α) (l : List ((_ : α) × β)) : β :=
|
||
(getValue? a l).get!
|
||
|
||
@[simp]
|
||
theorem getValue!_nil [BEq α] [Inhabited β] {a : α} :
|
||
getValue! a ([] : List ((_ : α) × β)) = default := (rfl)
|
||
|
||
theorem getValue!_eq_getValue? [BEq α] [Inhabited β] {l : List ((_ : α) × β)} {a : α} :
|
||
getValue! a l = (getValue? a l).get! := (rfl)
|
||
|
||
theorem getValue!_eq_default [BEq α] [Inhabited β] {l : List ((_ : α) × β)} {a : α}
|
||
(h : containsKey a l = false) : getValue! a l = default := by
|
||
rw [containsKey_eq_isSome_getValue?, Bool.eq_false_iff, ne_eq, Option.not_isSome_iff_eq_none] at h
|
||
rw [getValue!_eq_getValue?, h, Option.get!_none]
|
||
|
||
theorem getValue_eq_getValue! [BEq α] [Inhabited β] {l : List ((_ : α) × β)} {a : α}
|
||
(h : containsKey a l = true) : getValue a l h = getValue! a l := by
|
||
rw [getValue!_eq_getValue?, getValue, Option.get_eq_get!]
|
||
|
||
theorem getValue?_eq_some_getValue! [BEq α] [Inhabited β] {l : List ((_ : α) × β)} {a : α}
|
||
(h : containsKey a l = true) : getValue? a l = some (getValue! a l) := by
|
||
rw [getValue?_eq_some_getValue h, getValue_eq_getValue!]
|
||
|
||
theorem getValue!_eq_getValueCast! [BEq α] [LawfulBEq α] [Inhabited β] {l : List ((_ : α) × β)}
|
||
{a : α} : getValue! a l = getValueCast! a l := by
|
||
simp only [getValue!_eq_getValue?, getValueCast!_eq_getValueCast?, getValue?_eq_getValueCast?]
|
||
|
||
theorem getValue!_congr [BEq α] [PartialEquivBEq α] [Inhabited β] {l : List ((_ : α) × β)} {a b : α}
|
||
(hab : a == b) : getValue! a l = getValue! b l := by
|
||
simp only [getValue!_eq_getValue?, getValue?_congr hab]
|
||
|
||
theorem getValue!_eq_getValueD_default [BEq α] [Inhabited β] {l : List ((_ : α) × β)} {a : α} :
|
||
getValue! a l = getValueD a l default := (rfl)
|
||
|
||
end
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def getKey? [BEq α] (a : α) : List ((a : α) × β a) → Option α
|
||
| [] => none
|
||
| ⟨k, _⟩ :: l => bif k == a then some k else getKey? a l
|
||
|
||
@[simp] theorem getKey?_nil [BEq α] {a : α} :
|
||
getKey? a ([] : List ((a : α) × β a)) = none := (rfl)
|
||
|
||
@[simp] theorem getKey?_cons [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} :
|
||
getKey? a (⟨k, v⟩ :: l) = bif k == a then some k else getKey? a l := (rfl)
|
||
|
||
theorem getKey?_cons_of_true [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} (h : k == a) :
|
||
getKey? a (⟨k, v⟩ :: l) = some k := by
|
||
simp [h]
|
||
|
||
theorem getKey?_cons_of_false [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k}
|
||
(h : (k == a) = false) : getKey? a (⟨k, v⟩ :: l) = getKey? a l := by
|
||
simp [h]
|
||
|
||
theorem getKey?_eq_getEntry? [BEq α] {l : List ((a : α) × β a)} {a : α} :
|
||
getKey? a l = (getEntry? a l).map (·.1) := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k v l ih =>
|
||
cases h : k == a
|
||
· rw [getEntry?_cons_of_false h, getKey?_cons_of_false h, ih]
|
||
· rw [getEntry?_cons_of_true h, getKey?_cons_of_true h, Option.map_some]
|
||
|
||
theorem fst_mem_keys_of_mem [BEq α] [EquivBEq α] {a : (a : α) × β a} {l : List ((a : α) × β a)}
|
||
(hm : a ∈ l) : a.1 ∈ keys l :=
|
||
keys_eq_map ▸ List.mem_map_of_mem hm
|
||
|
||
theorem getKey?_eq_some_iff [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {k k'}
|
||
(hd : DistinctKeys l) :
|
||
getKey? k l = some k' ↔ k == k' ∧ k' ∈ keys l := by
|
||
simp [getKey?_eq_getEntry?, getEntry?_eq_some_iff hd]
|
||
apply Iff.intro
|
||
· rintro ⟨a, ⟨hbeq, hm⟩, rfl⟩
|
||
exact ⟨hbeq, fst_mem_keys_of_mem hm⟩
|
||
· rintro ⟨hbeq, hm⟩
|
||
simp only [keys_eq_map, List.mem_map] at hm
|
||
obtain ⟨a, hm, rfl⟩ := hm
|
||
refine ⟨a, ⟨hbeq, hm⟩, rfl⟩
|
||
|
||
theorem getKey?_beq [BEq α] {l : List ((a : α) × β a)} {a : α} :
|
||
(getKey? a l).all (· == a) := by
|
||
induction l using assoc_induction with
|
||
| nil => rfl
|
||
| cons k v l ih =>
|
||
rw [getKey?_cons, cond_eq_ite]
|
||
split <;> assumption
|
||
|
||
theorem getKey?_congr [BEq α] [EquivBEq α] {l : List ((a : α) × β a)}
|
||
{k k' : α} (h : k == k') : getKey? k l = getKey? k' l := by
|
||
induction l with
|
||
| nil => rfl
|
||
| cons x l ih =>
|
||
rw [getKey?_cons, getKey?_cons, BEq.congr_right h, ih]
|
||
|
||
theorem containsKey_eq_isSome_getKey? [BEq α] {l : List ((a : α) × β a)} {a : α} :
|
||
containsKey a l = (getKey? a l).isSome := by
|
||
simp [containsKey_eq_isSome_getEntry?, getKey?_eq_getEntry?]
|
||
|
||
theorem getEntry?_eq_some_iff_getKey?_eq_some_getValue?_eq_some [BEq α] {β : Type v}
|
||
{l : List ((_ : α) × β)} {k k' : α} {v : β} :
|
||
getEntry? k l = some ⟨k', v⟩ ↔ getKey? k l = some k' ∧ getValue? k l = some v := by
|
||
induction l with
|
||
| nil => simp
|
||
| cons hd tl ih =>
|
||
simp [getEntry?, getKey?, getValue?, cond_eq_ite]
|
||
split
|
||
· rename_i h
|
||
simp [Sigma.ext_iff]
|
||
· rw [ih]
|
||
|
||
theorem containsKey_of_getKey?_eq_some [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {a a' : α}
|
||
(h : getKey? a l = some a') :
|
||
containsKey a' l = true := by
|
||
have := @getKey?_beq _ _ _ l a
|
||
simp only [h, Option.all_some] at this
|
||
rw [← getKey?_congr this] at h
|
||
simp [containsKey_eq_isSome_getKey?, h]
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def getKey [BEq α] (a : α) (l : List ((a : α) × β a)) (h : containsKey a l) : α :=
|
||
(getKey? a l).get <| containsKey_eq_isSome_getKey?.symm.trans h
|
||
|
||
theorem getKey?_eq_some_getKey [BEq α] {l : List ((a : α) × β a)} {a : α} (h : containsKey a l) :
|
||
getKey? a l = some (getKey a l h) := by
|
||
simp [getKey]
|
||
|
||
theorem getKey_cons [BEq α] {l : List ((a : α) × β a)} {k a : α} {v : β k} {h} :
|
||
getKey a (⟨k, v⟩ :: l) h = if h' : k == a then k
|
||
else getKey a l (containsKey_of_containsKey_cons (k := k) h (Bool.eq_false_iff.2 h')) := by
|
||
rw [← Option.some_inj, ← getKey?_eq_some_getKey, getKey?_cons, apply_dite Option.some,
|
||
cond_eq_ite]
|
||
split
|
||
· rfl
|
||
· exact getKey?_eq_some_getKey _
|
||
|
||
theorem getKey?_eq_some_iff' [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {k k'} :
|
||
getKey? k l = some k' ↔ ∃ h, getKey k l h = k' := by
|
||
by_cases h : containsKey k l
|
||
· simp [h, getKey?_eq_some_getKey]
|
||
· simp only [h]
|
||
simp only [containsKey_eq_isSome_getKey?, Bool.not_eq_true, Option.isSome_eq_false_iff,
|
||
Option.isNone_iff_eq_none] at h
|
||
simp [h]
|
||
|
||
theorem getKey_beq [BEq α] {l : List ((a : α) × β a)} {a : α} (h : containsKey a l) :
|
||
getKey a l h == a := by
|
||
simpa only [getKey?_eq_some_getKey h] using getKey?_beq (l := l) (a := a)
|
||
|
||
@[simp]
|
||
theorem getKey_eq [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α} (h : containsKey a l) :
|
||
getKey a l h = a := by
|
||
simpa only [beq_iff_eq] using getKey_beq h
|
||
|
||
theorem getKey?_eq_some [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
(h : containsKey a l) : getKey? a l = some a := by
|
||
simp only [getKey?_eq_some_getKey h, getKey_eq]
|
||
|
||
theorem getKey_congr [BEq α] [EquivBEq α] {l : List ((a : α) × β a)}
|
||
{k k' : α} (h : k == k') {h'} {h''} : getKey k l h' = getKey k' l h'' := by
|
||
simpa only [getKey?_eq_some_getKey, h', h'', Option.some.injEq] using getKey?_congr (l := l) h
|
||
|
||
theorem getKey_of_mem [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {x : (a : α) × β a} (h : x ∈ l)
|
||
(distinct : DistinctKeys l) {h'} :
|
||
getKey x.fst l h' = x.fst := by
|
||
induction l with
|
||
| nil => simp at h
|
||
| cons hd tl ih =>
|
||
rw [containsKey_cons] at h'
|
||
by_cases hd_x : hd.1 == x.1
|
||
· have : x = hd := by
|
||
simp only [List.mem_cons] at h
|
||
cases h with
|
||
| inl h => exact h
|
||
| inr h =>
|
||
rw [distinctKeys_cons_iff] at distinct
|
||
rw [containsKey_eq_false_iff] at distinct
|
||
have := And.right distinct
|
||
specialize this x h
|
||
simp [this] at hd_x
|
||
simp only [← this]
|
||
rw [getKey_cons]
|
||
simp
|
||
· rw [getKey_cons]
|
||
rw [distinctKeys_cons_iff] at distinct
|
||
simp only [hd_x, Bool.false_eq_true, ↓reduceDIte]
|
||
simp only [Bool.not_eq_true] at hd_x
|
||
have hd_x' : ¬ x = hd := by
|
||
false_or_by_contra
|
||
rename_i h'
|
||
simp [h'] at hd_x
|
||
simp only [List.mem_cons, hd_x', false_or] at h
|
||
apply ih h (And.left distinct)
|
||
|
||
theorem getKey_eq_getEntry_fst [BEq α] {l : List ((a : α) × β a)} {a : α}
|
||
{h : containsKey a l} : getKey a l h = (getEntry a l h).fst := by
|
||
simp [getKey, getKey?_eq_getEntry?, Option.get_map, getEntry]
|
||
|
||
theorem forall_mem_keys_iff_forall_containsKey_getKey [BEq α] [EquivBEq α] {l : List ((a : α) × β a)}
|
||
{p : α → Prop} (hl : DistinctKeys l) :
|
||
(∀ k ∈ List.keys l, p k) ↔ ∀ (k : α) (h : containsKey k l), p (getKey k l h) := by
|
||
induction l using assoc_induction with
|
||
| nil => simp
|
||
| cons k' v tl ih =>
|
||
rw [distinctKeys_cons_iff] at hl
|
||
specialize ih (And.left hl)
|
||
simp only [keys_cons, List.mem_cons, forall_eq_or_imp, containsKey_cons, Bool.or_eq_true]
|
||
constructor
|
||
· intro h k h'
|
||
cases h' with
|
||
| inl h' =>
|
||
simp [getKey, h', h]
|
||
| inr h' =>
|
||
simp only [getKey_cons]
|
||
split
|
||
· rename_i k_k'
|
||
rw [containsKey_congr k_k'] at hl
|
||
simp [And.right hl] at h'
|
||
· rw [ih] at h
|
||
apply And.right h
|
||
· intro h
|
||
constructor
|
||
· specialize h k'
|
||
simp only [BEq.rfl, true_or, getKey_cons, ↓reduceDIte, forall_const] at h
|
||
exact h
|
||
· rw [ih]
|
||
intro k hk
|
||
specialize h k (Or.inr hk)
|
||
simp only [getKey_cons] at h
|
||
split at h
|
||
· rename_i hk'
|
||
rw [containsKey_congr hk'] at hl
|
||
simp [hk] at hl
|
||
· exact h
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
@[expose] def getKeyD [BEq α] (a : α) (l : List ((a : α) × β a)) (fallback : α) : α :=
|
||
(getKey? a l).getD fallback
|
||
|
||
@[simp]
|
||
theorem getKeyD_nil [BEq α] {a fallback : α} :
|
||
getKeyD a ([] : List ((a : α) × β a)) fallback = fallback := (rfl)
|
||
|
||
theorem getKeyD_eq_getKey? [BEq α] {l : List ((a : α) × β a)} {a fallback : α} :
|
||
getKeyD a l fallback = (getKey? a l).getD fallback := (rfl)
|
||
|
||
theorem getKeyD_eq_fallback [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {a fallback : α}
|
||
(h : containsKey a l = false) : getKeyD a l fallback = fallback := by
|
||
rw [containsKey_eq_isSome_getKey?, Bool.eq_false_iff, ne_eq,
|
||
Option.not_isSome_iff_eq_none] at h
|
||
rw [getKeyD_eq_getKey?, h, Option.getD_none]
|
||
|
||
theorem getKey_eq_getKeyD [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {a fallback : α}
|
||
(h : containsKey a l = true) :
|
||
getKey a l h = getKeyD a l fallback := by
|
||
rw [getKeyD_eq_getKey?, getKey, Option.get_eq_getD]
|
||
|
||
theorem getKeyD_congr [BEq α] [EquivBEq α] {l : List ((a : α) × β a)}
|
||
{k k' fallback : α} (h : k == k') : getKeyD k l fallback = getKeyD k' l fallback := by
|
||
simp only [getKeyD_eq_getKey?, getKey?_congr h]
|
||
|
||
theorem getKeyD_eq_of_containsKey [BEq α] [LawfulBEq α]
|
||
{l : List ((a : α) × β a)} {k fallback : α} (h : containsKey k l) :
|
||
getKeyD k l fallback = k := by
|
||
simp only [← getKey_eq_getKeyD h, getKey_eq]
|
||
|
||
theorem getKey?_eq_some_getKeyD [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {a fallback : α}
|
||
(h : containsKey a l = true) :
|
||
getKey? a l = some (getKeyD a l fallback) := by
|
||
rw [getKey?_eq_some_getKey h, getKey_eq_getKeyD]
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
@[expose] def getKey! [BEq α] [Inhabited α] (a : α) (l : List ((a : α) × β a)) : α :=
|
||
(getKey? a l).get!
|
||
|
||
@[simp]
|
||
theorem getKey!_nil [BEq α] [Inhabited α] {a : α} :
|
||
getKey! a ([] : List ((a : α) × β a)) = default := (rfl)
|
||
|
||
theorem getKey!_eq_getKey? [BEq α] [Inhabited α] {l : List ((a : α) × β a)} {a : α} :
|
||
getKey! a l = (getKey? a l).get! := (rfl)
|
||
|
||
theorem getKey!_eq_default [BEq α] [Inhabited α] {l : List ((a : α) × β a)} {a : α}
|
||
(h : containsKey a l = false) : getKey! a l = default := by
|
||
rw [containsKey_eq_isSome_getKey?, Bool.eq_false_iff, ne_eq,
|
||
Option.not_isSome_iff_eq_none] at h
|
||
rw [getKey!_eq_getKey?, h, Option.get!_none]
|
||
|
||
theorem getKey_eq_getKey! [BEq α] [Inhabited α] {l : List ((a : α) × β a)} {a : α}
|
||
(h : containsKey a l = true) : getKey a l h = getKey! a l := by
|
||
rw [getKey!_eq_getKey?, getKey, Option.get_eq_get!]
|
||
|
||
theorem getKey!_congr [BEq α] [EquivBEq α] [Inhabited α] {l : List ((a : α) × β a)}
|
||
{k k' : α} (h : k == k') : getKey! k l = getKey! k' l := by
|
||
simp only [getKey!_eq_getKey?, getKey?_congr h]
|
||
|
||
theorem getKey!_eq_of_containsKey [BEq α] [LawfulBEq α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} {k : α} (h : containsKey k l) :
|
||
getKey! k l = k := by
|
||
simp only [← getKey_eq_getKey! h, getKey_eq]
|
||
|
||
theorem getKey?_eq_some_getKey! [BEq α] [Inhabited α] {l : List ((a : α) × β a)} {a : α}
|
||
(h : containsKey a l = true) :
|
||
getKey? a l = some (getKey! a l) := by
|
||
rw [getKey?_eq_some_getKey h, getKey_eq_getKey!]
|
||
|
||
theorem getKey!_eq_getKeyD_default [BEq α] [EquivBEq α] [Inhabited α] {l : List ((a : α) × β a)}
|
||
{a : α} : getKey! a l = getKeyD a l default := (rfl)
|
||
|
||
theorem getEntry?_eq_getValueCast? [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)}
|
||
{a : α} : getEntry? a l = (getValueCast? a l).map (fun v => ⟨a, v⟩) := by
|
||
induction l using assoc_induction with
|
||
| nil => rfl
|
||
| cons k v l ih =>
|
||
simp only [getEntry?_cons, getValueCast?_cons, cond_eq_ite]
|
||
split
|
||
· rename_i h
|
||
simp only [beq_iff_eq] at h
|
||
subst h
|
||
rfl
|
||
· exact ih
|
||
|
||
theorem getEntry_eq_getKey_getValue [BEq α] {β : Type v} {l : List ((_ : α) × β)}
|
||
{a : α} (h : containsKey a l) : getEntry a l h = ⟨getKey a l h, getValue a l h⟩ := by
|
||
induction l using assoc_induction with
|
||
| nil => contradiction
|
||
| cons k v l ih =>
|
||
match h' : k == a with
|
||
| true =>
|
||
simp only [getEntry_cons_of_beq, getKey_cons, getValue_cons_of_beq, h', reduceDIte]
|
||
| false =>
|
||
simp only [getEntry_cons_of_false, getKey_cons, getValue_cons_of_false, h',
|
||
Bool.false_eq_true, reduceDIte]
|
||
apply ih
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def replaceEntry [BEq α] (k : α) (v : β k) : List ((a : α) × β a) → List ((a : α) × β a)
|
||
| [] => []
|
||
| ⟨k', v'⟩ :: l => bif k' == k then ⟨k, v⟩ :: l else ⟨k', v'⟩ :: replaceEntry k v l
|
||
|
||
@[simp] theorem replaceEntry_nil [BEq α] {k : α} {v : β k} : replaceEntry k v [] = [] := (rfl)
|
||
theorem replaceEntry_cons [BEq α] {l : List ((a : α) × β a)} {k k' : α} {v : β k} {v' : β k'} :
|
||
replaceEntry k v (⟨k', v'⟩ :: l) =
|
||
bif k' == k then ⟨k, v⟩ :: l else ⟨k', v'⟩ :: replaceEntry k v l := (rfl)
|
||
|
||
theorem replaceEntry_cons_of_true [BEq α] {l : List ((a : α) × β a)} {k k' : α} {v : β k}
|
||
{v' : β k'} (h : k' == k) : replaceEntry k v (⟨k', v'⟩ :: l) = ⟨k, v⟩ :: l := by
|
||
simp [replaceEntry, h]
|
||
|
||
theorem replaceEntry_cons_of_false [BEq α] {l : List ((a : α) × β a)} {k k' : α} {v : β k}
|
||
{v' : β k'} (h : (k' == k) = false) :
|
||
replaceEntry k v (⟨k', v'⟩ :: l) = ⟨k', v'⟩ :: replaceEntry k v l := by
|
||
simp [replaceEntry, h]
|
||
|
||
theorem replaceEntry_of_containsKey_eq_false [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k}
|
||
(h : containsKey k l = false) : replaceEntry k v l = l := by
|
||
induction l
|
||
· simp
|
||
next k v l ih =>
|
||
rw [containsKey_cons_eq_false] at h
|
||
rw [replaceEntry_cons_of_false h.1, ih h.2]
|
||
|
||
@[simp]
|
||
theorem isEmpty_replaceEntry [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
(replaceEntry k v l).isEmpty = l.isEmpty := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
· simp only [replaceEntry_cons, cond_eq_ite, List.isEmpty_cons]
|
||
split <;> simp
|
||
|
||
theorem mem_replaceEntry_of_beq_eq_false [BEq α] [EquivBEq α] {a : α} {b : β a}
|
||
{l : List ((a : α) × β a)} (p : (a : α) × β a) (hne : (p.1 == a) = false) :
|
||
p ∈ replaceEntry a b l ↔ p ∈ l := by
|
||
induction l
|
||
· simp only [replaceEntry_nil]
|
||
next ih =>
|
||
simp only [replaceEntry, cond_eq_ite]
|
||
split
|
||
next h =>
|
||
simp only [List.mem_cons, Sigma.ext_iff]
|
||
apply Iff.intro <;> exact fun
|
||
| Or.inr y => Or.inr y
|
||
| Or.inl y => by simp_all only [BEq.rfl, Bool.true_eq_false]
|
||
· simp only [List.mem_cons, ih]
|
||
|
||
theorem mem_replaceEntry_of_key_ne [BEq α] [LawfulBEq α] {a : α} {b : β a}
|
||
{l : List ((a : α) × β a)} (p : (a : α) × β a) (hne : p.1 ≠ a) :
|
||
p ∈ replaceEntry a b l ↔ p ∈ l :=
|
||
mem_replaceEntry_of_beq_eq_false p <| beq_false_of_ne hne
|
||
|
||
theorem getEntry?_replaceEntry_of_containsKey_eq_false [BEq α] {l : List ((a : α) × β a)} {a k : α}
|
||
{v : β k} (hl : containsKey k l = false) :
|
||
getEntry? a (replaceEntry k v l) = getEntry? a l := by
|
||
rw [replaceEntry_of_containsKey_eq_false hl]
|
||
|
||
theorem getEntry?_replaceEntry_of_false [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{a k : α} {v : β k} (h : (k == a) = false) :
|
||
getEntry? a (replaceEntry k v l) = getEntry? a l := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k' v' l ih =>
|
||
cases h' : k' == k
|
||
· 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 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) :
|
||
getEntry? a (replaceEntry k v l) = some ⟨k, v⟩ := by
|
||
induction l using assoc_induction
|
||
· simp at hl
|
||
next k' v' l ih =>
|
||
cases hk'a : k' == k
|
||
· rw [replaceEntry_cons_of_false hk'a]
|
||
have hk'k : (k' == a) = false := BEq.neq_of_neq_of_beq hk'a h
|
||
rw [getEntry?_cons_of_false hk'k]
|
||
exact ih (containsKey_of_containsKey_cons hl hk'a)
|
||
· rw [replaceEntry_cons_of_true hk'a, getEntry?_cons_of_true h]
|
||
|
||
theorem getEntry?_replaceEntry [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {a k : α}
|
||
{v : β k} :
|
||
getEntry? a (replaceEntry k v l) = if containsKey k l ∧ k == a then some ⟨k, v⟩ else
|
||
getEntry? a l := by
|
||
cases hl : containsKey k l
|
||
· simp [getEntry?_replaceEntry_of_containsKey_eq_false hl]
|
||
· cases h : k == a
|
||
· simp [getEntry?_replaceEntry_of_false h]
|
||
· simp [getEntry?_replaceEntry_of_true hl h]
|
||
|
||
@[simp]
|
||
theorem containsKey_replaceEntry [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {a k : α}
|
||
{v : β k} : containsKey a (replaceEntry k v l) = containsKey a l := by
|
||
by_cases h : (getEntry? k l).isSome ∧ k == a
|
||
· simp only [containsKey_eq_isSome_getEntry?, getEntry?_replaceEntry, h, and_self, ↓reduceIte,
|
||
Option.isSome_some, Bool.true_eq]
|
||
rw [← getEntry?_congr h.2, h.1]
|
||
· simp [containsKey_eq_isSome_getEntry?, getEntry?_replaceEntry, h]
|
||
|
||
theorem getEntry_replaceEntry_of_true [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{a k : α} {v : β k} (hl) (h : k == a) :
|
||
getEntry a (replaceEntry k v l) hl = ⟨k, v⟩ := by
|
||
rw [containsKey_replaceEntry] at hl
|
||
simp only [getEntry, getEntry?_replaceEntry]
|
||
simp_all [containsKey_congr h]
|
||
|
||
@[deprecated getEntry_mem (since := "2025-10-29")]
|
||
theorem mem_getEntry [BEq α] {l : List ((a : α) × β a)} {k : α} (hl : containsKey k l) :
|
||
getEntry k l hl ∈ l := by
|
||
induction l using assoc_induction
|
||
· simp at hl
|
||
next k' v' l ih =>
|
||
simp [getEntry, getEntry?_cons, cond_eq_ite]
|
||
split
|
||
· simp
|
||
· simp only [containsKey_cons, Bool.or_eq_true] at hl
|
||
simp_all [getEntry]
|
||
|
||
theorem mem_replaceEntry_of_true [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{k : α} {v : β k} (hl : containsKey k l = true) :
|
||
⟨k, v⟩ ∈ replaceEntry k v l := by
|
||
induction l using assoc_induction
|
||
· simp at hl
|
||
next k' v' l ih =>
|
||
cases h : k' == k <;> simp_all [replaceEntry_cons]
|
||
|
||
@[simp]
|
||
theorem length_replaceEntry [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
(replaceEntry k v l).length = l.length := by
|
||
induction l using assoc_induction <;> simp_all [replaceEntry_cons, Bool.apply_cond List.length]
|
||
|
||
section
|
||
|
||
variable {β : Type v}
|
||
|
||
theorem getValue?_replaceEntry_of_containsKey_eq_false [BEq α] {l : List ((_ : α) × β)} {k a : α}
|
||
{v : β} (hl : containsKey k l = false) : getValue? a (replaceEntry k v l) = getValue? a l := by
|
||
simp [getValue?_eq_getEntry?, getEntry?_replaceEntry_of_containsKey_eq_false hl]
|
||
|
||
theorem getValue?_replaceEntry_of_false [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)}
|
||
{k a : α} {v : β} (h : (k == a) = false) :
|
||
getValue? a (replaceEntry k v l) = getValue? a l := by
|
||
simp [getValue?_eq_getEntry?, getEntry?_replaceEntry_of_false h]
|
||
|
||
theorem getValue?_replaceEntry_of_true [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)}
|
||
{k a : α} {v : β} (hl : containsKey k l = true) (h : k == a) :
|
||
getValue? a (replaceEntry k v l) = some v := by
|
||
simp [getValue?_eq_getEntry?, getEntry?_replaceEntry_of_true hl h]
|
||
|
||
end
|
||
|
||
theorem getValueCast?_replaceEntry [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {a k : α}
|
||
{v : β k} : getValueCast? a (replaceEntry k v l) =
|
||
if h : containsKey k l ∧ k == a then some (cast (congrArg β (eq_of_beq h.2)) v)
|
||
else getValueCast? a l := by
|
||
rw [getValueCast?_eq_getEntry?]
|
||
split
|
||
next h =>
|
||
simp only [getEntry?_replaceEntry_of_true h.1 h.2, Option.dmap_some]
|
||
next h =>
|
||
simp only [Decidable.not_and_iff_not_or_not] at h
|
||
rcases h with h|h
|
||
· simp only [getEntry?_replaceEntry_of_containsKey_eq_false (Bool.eq_false_iff.2 h),
|
||
getValueCast?_eq_getEntry?]
|
||
· simp only [getEntry?_replaceEntry_of_false (Bool.eq_false_iff.2 h),
|
||
getValueCast?_eq_getEntry?]
|
||
|
||
theorem getKey?_replaceEntry [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {a k : α}
|
||
{v : β k} : getKey? a (replaceEntry k v l) =
|
||
if containsKey k l ∧ k == a then some k else getKey? a l := by
|
||
rw [getKey?_eq_getEntry?]
|
||
split
|
||
next h => simp [getEntry?_replaceEntry_of_true h.1 h.2]
|
||
next h =>
|
||
simp only [Decidable.not_and_iff_not_or_not] at h
|
||
rcases h with h|h
|
||
· rw [getEntry?_replaceEntry_of_containsKey_eq_false (Bool.eq_false_iff.2 h), getKey?_eq_getEntry?]
|
||
· rw [getEntry?_replaceEntry_of_false (Bool.eq_false_iff.2 h), getKey?_eq_getEntry?]
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def eraseKey [BEq α] (k : α) : List ((a : α) × β a) → List ((a : α) × β a)
|
||
| [] => []
|
||
| ⟨k', v'⟩ :: l => bif k' == k then l else ⟨k', v'⟩ :: eraseKey k l
|
||
|
||
@[simp] theorem eraseKey_nil [BEq α] {k : α} : eraseKey k ([] : List ((a : α) × β a)) = [] := (rfl)
|
||
|
||
theorem eraseKey_cons [BEq α] {l : List ((a : α) × β a)} {k k' : α} {v' : β k'} :
|
||
eraseKey k (⟨k', v'⟩ :: l) = bif k' == k then l else ⟨k', v'⟩ :: eraseKey k l := (rfl)
|
||
|
||
theorem eraseKey_cons_of_beq [BEq α] {l : List ((a : α) × β a)} {k k' : α} {v' : β k'}
|
||
(h : k' == k) : eraseKey k (⟨k', v'⟩ :: l) = l :=
|
||
by simp [eraseKey_cons, h]
|
||
|
||
@[simp]
|
||
theorem eraseKey_cons_self [BEq α] [ReflBEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
eraseKey k (⟨k, v⟩ :: l) = l :=
|
||
eraseKey_cons_of_beq BEq.rfl
|
||
|
||
theorem eraseKey_cons_of_false [BEq α] {l : List ((a : α) × β a)} {k k' : α} {v' : β k'}
|
||
(h : (k' == k) = false) : eraseKey k (⟨k', v'⟩ :: l) = ⟨k', v'⟩ :: eraseKey k l := by
|
||
simp [eraseKey_cons, h]
|
||
|
||
theorem eraseKey_of_containsKey_eq_false [BEq α] {l : List ((a : α) × β a)} {k : α}
|
||
(h : containsKey k l = false) : eraseKey k l = l := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k' v' t ih =>
|
||
simp only [containsKey_cons, Bool.or_eq_false_iff] at h
|
||
rw [eraseKey_cons_of_false h.1, ih h.2]
|
||
|
||
theorem mem_eraseKey_of_key_beq_eq_false [BEq α] {a : α}
|
||
{l : List ((a : α) × β a)} (p : (a : α) × β a) (hne : (p.1 == a) = false) :
|
||
p ∈ eraseKey a l ↔ p ∈ l := by
|
||
induction l
|
||
· simp only [eraseKey_nil]
|
||
next ih =>
|
||
simp only [eraseKey, List.mem_cons]
|
||
rw [cond_eq_ite]
|
||
split
|
||
next h =>
|
||
rw [iff_or_self, Sigma.ext_iff]
|
||
intro ⟨h₁, h₂⟩
|
||
rw [h₁, h] at hne
|
||
contradiction
|
||
next h =>
|
||
simp only [List.mem_cons, ih]
|
||
|
||
theorem mem_eraseKey_of_key_ne [BEq α] [LawfulBEq α] {a : α}
|
||
{l : List ((a : α) × β a)} (p : (a : α) × β a) (hne : p.1 ≠ a) : p ∈ eraseKey a l ↔ p ∈ l :=
|
||
mem_eraseKey_of_key_beq_eq_false p <| beq_false_of_ne hne
|
||
|
||
theorem sublist_eraseKey [BEq α] {l : List ((a : α) × β a)} {k : α} :
|
||
Sublist (eraseKey k l) l := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k' v' t ih =>
|
||
rw [eraseKey_cons]
|
||
cases k' == k
|
||
· simpa
|
||
· simp
|
||
|
||
theorem length_eraseKey [BEq α] {l : List ((a : α) × β a)} {k : α} :
|
||
(eraseKey k l).length = if containsKey k l then l.length - 1 else l.length := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k' v' t ih =>
|
||
rw [eraseKey_cons, containsKey_cons]
|
||
cases k' == k
|
||
· rw [cond_false, Bool.false_or, List.length_cons, ih]
|
||
cases h : containsKey k t
|
||
· simp
|
||
· simp only [List.length_cons, Nat.add_sub_cancel, if_true]
|
||
rw [Nat.sub_add_cancel]
|
||
cases t
|
||
· simp at h
|
||
· simp
|
||
· simp
|
||
|
||
theorem length_eraseKey_le [BEq α] {l : List ((a : α) × β a)} {k : α} :
|
||
(eraseKey k l).length ≤ l.length :=
|
||
sublist_eraseKey.length_le
|
||
|
||
theorem length_le_length_eraseKey [BEq α] {l : List ((a : α) × β a)} {k : α} :
|
||
l.length ≤ (eraseKey k l).length + 1 := by
|
||
rw [length_eraseKey]
|
||
split <;> omega
|
||
|
||
theorem isEmpty_eraseKey [BEq α] {l : List ((a : α) × β a)} {k : α} :
|
||
(eraseKey k l).isEmpty = (l.isEmpty || (l.length == 1 && containsKey k l)) := by
|
||
rw [Bool.eq_iff_iff]
|
||
simp only [Bool.or_eq_true, Bool.and_eq_true, beq_iff_eq]
|
||
rw [List.isEmpty_iff_length_eq_zero, length_eraseKey, List.isEmpty_iff_length_eq_zero]
|
||
cases containsKey k l <;> cases l <;> simp
|
||
|
||
theorem DistinctKeys.replaceEntry [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
{v : β k} (h : DistinctKeys l) : DistinctKeys (replaceEntry k v l) := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k' v' l ih =>
|
||
rw [distinctKeys_cons_iff] at h
|
||
cases hk'k : k' == k
|
||
· rw [replaceEntry_cons_of_false hk'k, distinctKeys_cons_iff]
|
||
refine ⟨ih h.1, ?_⟩
|
||
simpa using h.2
|
||
· rw [replaceEntry_cons_of_true hk'k, distinctKeys_cons_iff]
|
||
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
|
||
|
||
@[simp]
|
||
theorem insertEntry_nil [BEq α] {k : α} {v : β k} :
|
||
insertEntry k v ([] : List ((a : α) × β a)) = [⟨k, v⟩] :=
|
||
by simp [insertEntry]
|
||
|
||
theorem insertEntry_cons_of_false [BEq α] {l : List ((a : α) × β a)} {k k' : α} {v : β k}
|
||
{v' : β k'} (h : (k' == k) = false) :
|
||
Perm (insertEntry k v (⟨k', v'⟩ :: l)) (⟨k', v'⟩ :: insertEntry k v l) := by
|
||
simp only [insertEntry, containsKey_cons, h, Bool.false_or, cond_eq_ite]
|
||
split
|
||
· rw [replaceEntry_cons_of_false h]
|
||
· apply Perm.swap
|
||
|
||
theorem insertEntry_cons_of_beq [BEq α] {l : List ((a : α) × β a)} {k k' : α} {v : β k} {v' : β k'}
|
||
(h : k' == k) : insertEntry k v (⟨k', v'⟩ :: l) = ⟨k, v⟩ :: l := by
|
||
simp_all only [insertEntry, containsKey_cons, Bool.true_or, cond_true, replaceEntry_cons_of_true]
|
||
|
||
@[simp]
|
||
theorem insertEntry_cons_self [BEq α] [ReflBEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
insertEntry k v (⟨k, v⟩ :: l) = ⟨k, v⟩ :: l :=
|
||
insertEntry_cons_of_beq BEq.rfl
|
||
|
||
theorem insertEntry_of_containsKey [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k}
|
||
(h : containsKey k l) : insertEntry k v l = replaceEntry k v l := by
|
||
simp [insertEntry, h]
|
||
|
||
theorem insertEntry_of_containsKey_eq_false [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k}
|
||
(h : containsKey k l = false) : insertEntry k v l = ⟨k, v⟩ :: l := by
|
||
simp [insertEntry, h]
|
||
|
||
theorem mem_insertEntry_of_key_beq_eq_false [BEq α] [EquivBEq α] {a : α} {b : β a}
|
||
{l : List ((a : α) × β a)} (p : (a : α) × β a)
|
||
(hne : (p.1 == a) = false) : p ∈ insertEntry a b l ↔ p ∈ l := by
|
||
simp only [insertEntry, cond_eq_ite]
|
||
split
|
||
· exact mem_replaceEntry_of_beq_eq_false p hne
|
||
· simp only [List.mem_cons, or_iff_right_iff_imp, Sigma.ext_iff]
|
||
rw [← Bool.not_eq_true] at hne
|
||
exact fun x => hne (beq_of_eq x.1) |> False.elim
|
||
|
||
theorem mem_insertEntry_of_key_ne [BEq α] [LawfulBEq α] {a : α} {b : β a}
|
||
{l : List ((a : α) × β a)} (p : (a : α) × β a)
|
||
(hne : p.1 ≠ a) : p ∈ insertEntry a b l ↔ p ∈ l :=
|
||
mem_insertEntry_of_key_beq_eq_false p <| beq_false_of_ne hne
|
||
|
||
theorem DistinctKeys.insertEntry [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
{v : β k} (h : DistinctKeys l) : DistinctKeys (insertEntry k v l) := by
|
||
cases h' : containsKey k l
|
||
· rw [insertEntry_of_containsKey_eq_false h', distinctKeys_cons_iff]
|
||
exact ⟨h, h'⟩
|
||
· rw [insertEntry_of_containsKey h']
|
||
exact h.replaceEntry
|
||
|
||
@[simp]
|
||
theorem isEmpty_insertEntry [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
(insertEntry k v l).isEmpty = false := by
|
||
cases h : containsKey k l
|
||
· simp [insertEntry_of_containsKey_eq_false h]
|
||
· rw [insertEntry_of_containsKey h, isEmpty_replaceEntry, isEmpty_eq_false_of_containsKey h]
|
||
|
||
theorem length_insertEntry [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
(insertEntry k v l).length = if containsKey k l then l.length else l.length + 1 := by
|
||
simp [insertEntry, Bool.apply_cond List.length]
|
||
|
||
theorem length_le_length_insertEntry [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
l.length ≤ (insertEntry k v l).length := by
|
||
rw [length_insertEntry]
|
||
split <;> omega
|
||
|
||
theorem length_insertEntry_le [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
(insertEntry k v l).length ≤ l.length + 1 := by
|
||
rw [length_insertEntry]
|
||
split <;> omega
|
||
|
||
section
|
||
|
||
variable {β : Type v}
|
||
|
||
theorem getValue?_insertEntry_of_beq [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)} {k a : α}
|
||
{v : β} (h : k == a) : getValue? a (insertEntry k v l) = some v := by
|
||
cases h' : containsKey k l
|
||
· rw [insertEntry_of_containsKey_eq_false h', getValue?_cons_of_true h]
|
||
· rw [insertEntry_of_containsKey h', getValue?_replaceEntry_of_true h' h]
|
||
|
||
theorem getValue?_insertEntry_of_self [BEq α] [EquivBEq α] {l : List ((_ : α) × β)} {k : α}
|
||
{v : β} : getValue? k (insertEntry k v l) = some v :=
|
||
getValue?_insertEntry_of_beq BEq.rfl
|
||
|
||
theorem getValue?_insertEntry_of_false [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)}
|
||
{k a : α} {v : β} (h : (k == a) = false) : getValue? a (insertEntry k v l) = getValue? a l := by
|
||
cases h' : containsKey k l
|
||
· rw [insertEntry_of_containsKey_eq_false h', getValue?_cons_of_false h]
|
||
· rw [insertEntry_of_containsKey h', getValue?_replaceEntry_of_false h]
|
||
|
||
theorem getValue?_insertEntry [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)} {k a : α}
|
||
{v : β} : getValue? a (insertEntry k v l) = if k == a then some v else getValue? a l := by
|
||
cases h : k == a
|
||
· simp [getValue?_insertEntry_of_false h]
|
||
· simp [getValue?_insertEntry_of_beq h]
|
||
|
||
theorem getValue?_insertEntry_self [BEq α] [EquivBEq α] {l : List ((_ : α) × β)} {k : α} {v : β} :
|
||
getValue? k (insertEntry k v l) = some v := by
|
||
simp [getValue?_insertEntry]
|
||
|
||
end
|
||
|
||
theorem getEntry?_insertEntry [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} :
|
||
getEntry? a (insertEntry k v l) = if k == a then some ⟨k, v⟩ else getEntry? a l := by
|
||
cases hl : containsKey k l
|
||
· rw [insertEntry_of_containsKey_eq_false hl, getEntry?_cons, cond_eq_ite]
|
||
· simp [insertEntry_of_containsKey hl, getEntry?_replaceEntry, hl]
|
||
|
||
theorem getValueCast?_insertEntry [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} : getValueCast? a (insertEntry k v l) =
|
||
if h : k == a then some (cast (congrArg β (eq_of_beq h)) v) else getValueCast? a l := by
|
||
cases hl : containsKey k l
|
||
· rw [insertEntry_of_containsKey_eq_false hl, getValueCast?_cons]
|
||
· rw [insertEntry_of_containsKey hl, getValueCast?_replaceEntry, hl]
|
||
split <;> simp_all
|
||
|
||
theorem getValueCast?_insertEntry_self [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
{v : β k} : getValueCast? k (insertEntry k v l) = some v := by
|
||
rw [getValueCast?_insertEntry, dif_pos BEq.rfl, cast_eq]
|
||
|
||
theorem getValueCast!_insertEntry [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
[Inhabited (β a)] {v : β k} : getValueCast! a (insertEntry k v l) =
|
||
if h : k == a then cast (congrArg β (eq_of_beq h)) v else getValueCast! a l := by
|
||
simp [getValueCast!_eq_getValueCast?, getValueCast?_insertEntry, apply_dite Option.get!]
|
||
|
||
theorem getValueCast!_insertEntry_self [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
[Inhabited (β k)] {v : β k} : getValueCast! k (insertEntry k v l) = v := by
|
||
rw [getValueCast!_insertEntry, dif_pos BEq.rfl, cast_eq]
|
||
|
||
theorem getValueCastD_insertEntry [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{fallback : β a} {v : β k} : getValueCastD a (insertEntry k v l) fallback =
|
||
if h : k == a then cast (congrArg β (eq_of_beq h)) v
|
||
else getValueCastD a l fallback := by
|
||
simp [getValueCastD_eq_getValueCast?, getValueCast?_insertEntry,
|
||
apply_dite (fun x => Option.getD x fallback)]
|
||
|
||
theorem getValueCastD_insertEntry_self [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
{fallback : β k} {v : β k} : getValueCastD k (insertEntry k v l) fallback = v := by
|
||
rw [getValueCastD_insertEntry, dif_pos BEq.rfl, cast_eq]
|
||
|
||
theorem getValue!_insertEntry {β : Type v} [BEq α] [PartialEquivBEq α] [Inhabited β]
|
||
{l : List ((_ : α) × β)} {k a : α} {v : β} :
|
||
getValue! a (insertEntry k v l) = if k == a then v else getValue! a l := by
|
||
simp [getValue!_eq_getValue?, getValue?_insertEntry, apply_ite Option.get!]
|
||
|
||
theorem getValue!_insertEntry_self {β : Type v} [BEq α] [EquivBEq α] [Inhabited β]
|
||
{l : List ((_ : α) × β)} {k : α} {v : β} : getValue! k (insertEntry k v l) = v := by
|
||
simp [getValue!_insertEntry, BEq.rfl]
|
||
|
||
theorem getValueD_insertEntry {β : Type v} [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)}
|
||
{k a : α} {fallback v : β} : getValueD a (insertEntry k v l) fallback =
|
||
if k == a then v else getValueD a l fallback := by
|
||
simp [getValueD_eq_getValue?, getValue?_insertEntry, apply_ite (fun x => Option.getD x fallback)]
|
||
|
||
theorem getValueD_insertEntry_self {β : Type v} [BEq α] [EquivBEq α] {l : List ((_ : α) × β)}
|
||
{k : α} {fallback v : β} : getValueD k (insertEntry k v l) fallback = v := by
|
||
simp [getValueD_insertEntry, BEq.rfl]
|
||
|
||
theorem getKey?_insertEntry [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} : getKey? a (insertEntry k v l) = if k == a then some k else getKey? a l := by
|
||
cases hl : containsKey k l
|
||
· simp [insertEntry_of_containsKey_eq_false hl]
|
||
· rw [insertEntry_of_containsKey hl, getKey?_replaceEntry, hl]
|
||
split <;> simp_all
|
||
|
||
theorem getKey?_insertEntry_self [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
{v : β k} : getKey? k (insertEntry k v l) = some k := by
|
||
simp [getKey?_insertEntry]
|
||
|
||
theorem getKey?_eq_none [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {a : α}
|
||
(h : containsKey a l = false) : getKey? a l = none := by
|
||
rwa [← Option.not_isSome_iff_eq_none, ← containsKey_eq_isSome_getKey?, Bool.not_eq_true]
|
||
|
||
theorem getKey!_insertEntry [BEq α] [EquivBEq α] [Inhabited α] {l : List ((a : α) × β a)}
|
||
{k a : α} {v : β k} : getKey! a (insertEntry k v l) =
|
||
if k == a then k else getKey! a l := by
|
||
simp [getKey!_eq_getKey?, getKey?_insertEntry, apply_ite Option.get!]
|
||
|
||
theorem getKey!_insertEntry_self [BEq α] [EquivBEq α] [Inhabited α] {l : List ((a : α) × β a)}
|
||
{k : α} {v : β k} : getKey! k (insertEntry k v l) = k := by
|
||
rw [getKey!_insertEntry, if_pos BEq.rfl]
|
||
|
||
theorem getKeyD_insertEntry [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {k a fallback : α}
|
||
{v : β k} : getKeyD a (insertEntry k v l) fallback =
|
||
if k == a then k else getKeyD a l fallback := by
|
||
simp [getKeyD_eq_getKey?, getKey?_insertEntry, apply_ite (fun x => Option.getD x fallback)]
|
||
|
||
theorem getKeyD_insertEntry_self [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {k fallback : α}
|
||
{v : β k} : getKeyD k (insertEntry k v l) fallback = k := by
|
||
rw [getKeyD_insertEntry, if_pos BEq.rfl]
|
||
|
||
@[local simp]
|
||
theorem containsKey_insertEntry [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} : containsKey a (insertEntry k v l) = ((k == a) || containsKey a l) := by
|
||
rw [containsKey_eq_isSome_getEntry?, containsKey_eq_isSome_getEntry?, getEntry?_insertEntry]
|
||
cases k == a <;> simp
|
||
|
||
theorem containsKey_insertEntry_of_beq [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{k a : α} {v : β k} (h : k == a) : containsKey a (insertEntry k v l) := by
|
||
simp [h]
|
||
|
||
theorem containsKey_insertEntry_self [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
{v : β k} : containsKey k (insertEntry k v l) :=
|
||
containsKey_insertEntry_of_beq BEq.rfl
|
||
|
||
theorem containsKey_of_containsKey_insertEntry [BEq α] [PartialEquivBEq α]
|
||
{l : List ((a : α) × β a)} {k a : α} {v : β k} (h₁ : containsKey a (insertEntry k v l))
|
||
(h₂ : (k == a) = false) : containsKey a l := by
|
||
rwa [containsKey_insertEntry, h₂, Bool.false_or] at h₁
|
||
|
||
theorem getValueCast_insertEntry [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} {h} : getValueCast a (insertEntry k v l) h =
|
||
if h' : k == a then cast (congrArg β (eq_of_beq h')) v
|
||
else getValueCast a l (containsKey_of_containsKey_insertEntry h (Bool.eq_false_iff.2 h')) := by
|
||
rw [← Option.some_inj, ← getValueCast?_eq_some_getValueCast, apply_dite Option.some,
|
||
getValueCast?_insertEntry]
|
||
simp only [← getValueCast?_eq_some_getValueCast]
|
||
|
||
theorem getValueCast_insertEntry_self [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
{v : β k} : getValueCast k (insertEntry k v l) containsKey_insertEntry_self = v := by
|
||
simp [getValueCast_insertEntry]
|
||
|
||
theorem getValue_insertEntry {β : Type v} [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)}
|
||
{k a : α} {v : β} {h} : getValue a (insertEntry k v l) h =
|
||
if h' : k == a then v
|
||
else getValue a l (containsKey_of_containsKey_insertEntry h (Bool.eq_false_iff.2 h')) := by
|
||
rw [← Option.some_inj, ← getValue?_eq_some_getValue, apply_dite Option.some,
|
||
getValue?_insertEntry, ← dite_eq_ite]
|
||
simp only [← getValue?_eq_some_getValue]
|
||
|
||
theorem getValue_insertEntry_self {β : Type v} [BEq α] [EquivBEq α] {l : List ((_ : α) × β)} {k : α}
|
||
{v : β} : getValue k (insertEntry k v l) containsKey_insertEntry_self = v := by
|
||
simp [getValue_insertEntry]
|
||
|
||
theorem getKey_insertEntry [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} {h} : getKey a (insertEntry k v l) h =
|
||
if h' : k == a then k
|
||
else getKey a l (containsKey_of_containsKey_insertEntry h (Bool.eq_false_iff.2 h')) := by
|
||
rw [← Option.some_inj, ← getKey?_eq_some_getKey, apply_dite Option.some, getKey?_insertEntry]
|
||
simp only [← getKey?_eq_some_getKey, dite_eq_ite]
|
||
|
||
theorem getKey_insertEntry_self [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
{v : β k} : getKey k (insertEntry k v l) containsKey_insertEntry_self = k := by
|
||
simp [getKey_insertEntry]
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def insertEntryIfNew [BEq α] (k : α) (v : β k) (l : List ((a : α) × β a)) : List ((a : α) × β a) :=
|
||
bif containsKey k l then l else ⟨k, v⟩ :: l
|
||
|
||
theorem insertEntryIfNew_of_containsKey [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k}
|
||
(h : containsKey k l) : insertEntryIfNew k v l = l := by
|
||
simp_all [insertEntryIfNew]
|
||
|
||
theorem insertEntryIfNew_of_containsKey_eq_false [BEq α] {l : List ((a : α) × β a)} {k : α}
|
||
{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.Internal.List.insertEntryIfNew, cond_eq_ite]
|
||
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
|
||
cases h : containsKey k l
|
||
· simp [insertEntryIfNew_of_containsKey_eq_false h]
|
||
· rw [insertEntryIfNew_of_containsKey h]
|
||
exact isEmpty_eq_false_of_containsKey h
|
||
|
||
theorem getEntry?_insertEntryIfNew [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} : getEntry? a (insertEntryIfNew k v l) =
|
||
if k == a && !containsKey k l then some ⟨k, v⟩ else getEntry? a l := by
|
||
cases h : containsKey k l
|
||
· simp [insertEntryIfNew_of_containsKey_eq_false h, getEntry?_cons]
|
||
· simp [insertEntryIfNew_of_containsKey h]
|
||
|
||
theorem getValueCast?_insertEntryIfNew [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} : getValueCast? a (insertEntryIfNew k v l) =
|
||
if h : k == a ∧ containsKey k l = false then some (cast (congrArg β (eq_of_beq h.1)) v)
|
||
else getValueCast? a l := by
|
||
cases h : containsKey k l
|
||
· rw [insertEntryIfNew_of_containsKey_eq_false h, getValueCast?_cons]
|
||
split <;> simp_all
|
||
· simp [insertEntryIfNew_of_containsKey h]
|
||
|
||
theorem getValue?_insertEntryIfNew {β : Type v} [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)}
|
||
{k a : α} {v : β} : getValue? a (insertEntryIfNew k v l) =
|
||
if k == a ∧ containsKey k l = false then some v else getValue? a l := by
|
||
simp [getValue?_eq_getEntry?, getEntry?_insertEntryIfNew,
|
||
apply_ite (Option.map (fun (y : ((_ : α) × β)) => y.2))]
|
||
|
||
theorem containsKey_insertEntryIfNew [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{k a : α} {v : β k} :
|
||
containsKey a (insertEntryIfNew k v l) = ((k == a) || containsKey a l) := by
|
||
simp only [containsKey_eq_isSome_getEntry?, getEntry?_insertEntryIfNew, apply_ite Option.isSome,
|
||
Option.isSome_some]
|
||
simp only [Bool.and_eq_true, Option.not_isSome, Option.isNone_iff_eq_none,
|
||
getEntry?_eq_none, Bool.if_true_left, Bool.decide_and, Bool.decide_eq_true,
|
||
Bool.decide_eq_false]
|
||
cases h : k == a
|
||
· simp
|
||
· rw [containsKey_eq_isSome_getEntry?, getEntry?_congr h]
|
||
simp [-Option.not_isSome]
|
||
|
||
theorem containsKey_insertEntryIfNew_self [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
{v : β k} : containsKey k (insertEntryIfNew k v l) := by
|
||
rw [containsKey_insertEntryIfNew, BEq.rfl, Bool.true_or]
|
||
|
||
theorem containsKey_of_containsKey_insertEntryIfNew [BEq α] [PartialEquivBEq α]
|
||
{l : List ((a : α) × β a)} {k a : α} {v : β k} (h₁ : containsKey a (insertEntryIfNew k v l))
|
||
(h₂ : (k == a) = false) : containsKey a l := by
|
||
rwa [containsKey_insertEntryIfNew, h₂, Bool.false_or] at h₁
|
||
|
||
/--
|
||
This is a restatement of `containsKey_insertEntryIfNew` that is written to exactly match the proof
|
||
obligation in the statement of `getValueCast_insertEntryIfNew`.
|
||
-/
|
||
theorem containsKey_of_containsKey_insertEntryIfNew' [BEq α] [PartialEquivBEq α]
|
||
{l : List ((a : α) × β a)} {k a : α} {v : β k} (h₁ : containsKey a (insertEntryIfNew k v l))
|
||
(h₂ : ¬((k == a) ∧ containsKey k l = false)) : containsKey a l := by
|
||
rw [Decidable.not_and_iff_or_not, Bool.not_eq_true, Bool.not_eq_false] at h₂
|
||
rcases h₂ with h₂|h₂
|
||
· rwa [containsKey_insertEntryIfNew, h₂, Bool.false_or] at h₁
|
||
· rwa [insertEntryIfNew_of_containsKey h₂] at h₁
|
||
|
||
theorem getValueCast_insertEntryIfNew [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} {h} : getValueCast a (insertEntryIfNew k v l) h =
|
||
if h' : k == a ∧ containsKey k l = false then
|
||
cast (congrArg β (eq_of_beq h'.1)) v
|
||
else
|
||
getValueCast a l (containsKey_of_containsKey_insertEntryIfNew' h h') := by
|
||
rw [← Option.some_inj, ← getValueCast?_eq_some_getValueCast, apply_dite Option.some,
|
||
getValueCast?_insertEntryIfNew]
|
||
simp only [← getValueCast?_eq_some_getValueCast]
|
||
|
||
theorem getValue_insertEntryIfNew {β : Type v} [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)}
|
||
{k a : α} {v : β} {h} : getValue a (insertEntryIfNew k v l) h =
|
||
if h' : k == a ∧ containsKey k l = false then v
|
||
else getValue a l (containsKey_of_containsKey_insertEntryIfNew' h h') := by
|
||
rw [← Option.some_inj, ← getValue?_eq_some_getValue, apply_dite Option.some,
|
||
getValue?_insertEntryIfNew, ← dite_eq_ite]
|
||
simp [← getValue?_eq_some_getValue]
|
||
|
||
theorem getValueCast!_insertEntryIfNew [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} [Inhabited (β a)] : getValueCast! a (insertEntryIfNew k v l) =
|
||
if h : k == a ∧ containsKey k l = false then cast (congrArg β (eq_of_beq h.1)) v
|
||
else getValueCast! a l := by
|
||
simp [getValueCast!_eq_getValueCast?, getValueCast?_insertEntryIfNew, apply_dite Option.get!]
|
||
|
||
theorem getValue!_insertEntryIfNew {β : Type v} [BEq α] [PartialEquivBEq α] [Inhabited β]
|
||
{l : List ((_ : α) × β)} {k a : α} {v : β} : getValue! a (insertEntryIfNew k v l) =
|
||
if k == a ∧ containsKey k l = false then v else getValue! a l := by
|
||
simp [getValue!_eq_getValue?, getValue?_insertEntryIfNew, apply_ite Option.get!]
|
||
|
||
theorem getValueCastD_insertEntryIfNew [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} {fallback : β a} : getValueCastD a (insertEntryIfNew k v l) fallback =
|
||
if h : k == a ∧ containsKey k l = false then cast (congrArg β (eq_of_beq h.1)) v
|
||
else getValueCastD a l fallback := by
|
||
simp [getValueCastD_eq_getValueCast?, getValueCast?_insertEntryIfNew,
|
||
apply_dite (fun x => Option.getD x fallback)]
|
||
|
||
theorem getValueD_insertEntryIfNew {β : Type v} [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)}
|
||
{k a : α} {fallback v : β} : getValueD a (insertEntryIfNew k v l) fallback =
|
||
if k == a ∧ containsKey k l = false then v else getValueD a l fallback := by
|
||
simp [getValueD_eq_getValue?, getValue?_insertEntryIfNew,
|
||
apply_ite (fun x => Option.getD x fallback)]
|
||
|
||
theorem getKey?_insertEntryIfNew [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{v : β k} : getKey? a (insertEntryIfNew k v l) =
|
||
if k == a ∧ containsKey k l = false then some k else getKey? a l := by
|
||
cases h : containsKey k l
|
||
· rw [insertEntryIfNew_of_containsKey_eq_false h]
|
||
split <;> simp_all
|
||
· simp [insertEntryIfNew_of_containsKey h]
|
||
|
||
theorem getKey_insertEntryIfNew [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{k a : α} {v : β k} {h} : getKey a (insertEntryIfNew k v l) h =
|
||
if h' : k == a ∧ containsKey k l = false then k
|
||
else getKey a l (containsKey_of_containsKey_insertEntryIfNew' h h') := by
|
||
rw [← Option.some_inj, ← getKey?_eq_some_getKey, apply_dite Option.some,
|
||
getKey?_insertEntryIfNew, ← dite_eq_ite]
|
||
simp [← getKey?_eq_some_getKey]
|
||
|
||
theorem getKey!_insertEntryIfNew [BEq α] [PartialEquivBEq α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} {k a : α} {v : β k} : getKey! a (insertEntryIfNew k v l) =
|
||
if k == a ∧ containsKey k l = false then k else getKey! a l := by
|
||
simp [getKey!_eq_getKey?, getKey?_insertEntryIfNew, apply_ite Option.get!]
|
||
|
||
theorem getKeyD_insertEntryIfNew [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{k a fallback : α} {v : β k} : getKeyD a (insertEntryIfNew k v l) fallback =
|
||
if k == a ∧ containsKey k l = false then k else getKeyD a l fallback := by
|
||
simp [getKeyD_eq_getKey?, getKey?_insertEntryIfNew, apply_ite (fun x => Option.getD x fallback)]
|
||
|
||
theorem length_insertEntryIfNew [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
(insertEntryIfNew k v l).length = if containsKey k l then l.length else l.length + 1 := by
|
||
simp [insertEntryIfNew, Bool.apply_cond List.length]
|
||
|
||
theorem length_le_length_insertEntryIfNew [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
l.length ≤ (insertEntryIfNew k v l).length := by
|
||
rw [length_insertEntryIfNew]
|
||
split <;> omega
|
||
|
||
theorem length_insertEntryIfNew_le [BEq α] {l : List ((a : α) × β a)} {k : α} {v : β k} :
|
||
(insertEntryIfNew k v l).length ≤ l.length + 1 := by
|
||
rw [length_insertEntryIfNew]
|
||
split <;> omega
|
||
|
||
@[simp]
|
||
theorem keys_eraseKey [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α} :
|
||
keys (eraseKey k l) = (keys l).erase k := by
|
||
induction l using assoc_induction
|
||
· rfl
|
||
next k' v' l ih =>
|
||
simp only [eraseKey_cons, keys_cons, List.erase_cons]
|
||
rw [BEq.comm]
|
||
cases k == k' <;> simp [ih]
|
||
|
||
theorem DistinctKeys.eraseKey [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α} :
|
||
DistinctKeys l → DistinctKeys (eraseKey k l) := by
|
||
apply distinctKeys_of_sublist_keys (by simpa using erase_sublist)
|
||
|
||
theorem getEntry?_eraseKey_self [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
(h : DistinctKeys l) : getEntry? k (eraseKey k l) = none := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k' v' t ih =>
|
||
cases h' : k' == k
|
||
· rw [eraseKey_cons_of_false h', getEntry?_cons_of_false h']
|
||
exact ih h.tail
|
||
· rw [eraseKey_cons_of_beq h', ← Option.not_isSome_iff_eq_none, Bool.not_eq_true,
|
||
← containsKey_eq_isSome_getEntry?, ← containsKey_congr h']
|
||
exact h.containsKey_eq_false
|
||
|
||
theorem getEntry?_eraseKey_of_beq [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
(hl : DistinctKeys l) (hka : k == a) : getEntry? a (eraseKey k l) = none := by
|
||
rw [← getEntry?_congr hka, getEntry?_eraseKey_self hl]
|
||
|
||
theorem getEntry?_eraseKey_of_false [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{k a : α} (hka : (k == a) = false) : getEntry? a (eraseKey k l) = getEntry? a l := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k' v' t ih =>
|
||
cases h' : k' == k
|
||
· rw [eraseKey_cons_of_false h']
|
||
cases h'' : k' == a
|
||
· rw [getEntry?_cons_of_false h'', ih, getEntry?_cons_of_false h'']
|
||
· rw [getEntry?_cons_of_true h'', getEntry?_cons_of_true h'']
|
||
· rw [eraseKey_cons_of_beq h']
|
||
have hx : (k' == a) = false := BEq.neq_of_beq_of_neq h' hka
|
||
rw [getEntry?_cons_of_false hx]
|
||
|
||
theorem getEntry?_eraseKey [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
(hl : DistinctKeys l) :
|
||
getEntry? a (eraseKey k l) = if k == a then none else getEntry? a l := by
|
||
cases h : k == a
|
||
· simp [getEntry?_eraseKey_of_false h]
|
||
· simp [getEntry?_eraseKey_of_beq hl h]
|
||
|
||
theorem keys_filterMap' {l : List ((a : α) × β a)} {f : (a : α) → β a → Option (γ a)} :
|
||
keys (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩)) =
|
||
keys (l.filter fun p => (f p.1 p.2).isSome) := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k v t ih =>
|
||
simp only [List.filterMap_cons, List.filter_cons]
|
||
cases f k v <;> simp [ih]
|
||
|
||
theorem mem_keys_iff_contains [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k : α} :
|
||
k ∈ keys l ↔ containsKey k l = true := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k' v t ih =>
|
||
simp only [keys_cons, List.mem_cons, containsKey_cons, Bool.or_eq_true, beq_iff_eq]
|
||
rw [ih, Eq.comm]
|
||
|
||
theorem keys_filter [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {f : (a : α) → β a → Bool}
|
||
(hl : DistinctKeys l) :
|
||
(keys (l.filter (fun x => f x.1 x.2))) =
|
||
(List.filter (fun x => f x.1 (getValueCast x.1 l (mem_keys_iff_contains.mp x.2)))
|
||
(keys l).attach).unattach := by
|
||
induction l using assoc_induction with
|
||
| nil => simp [keys]
|
||
| cons k v tl ih =>
|
||
rw [List.filter_cons]
|
||
specialize ih hl.tail
|
||
replace hl := hl.containsKey_eq_false
|
||
simp only [keys, List.attach_cons, getValueCast_cons, ↓reduceDIte, cast_eq,
|
||
List.filter_cons, BEq.rfl, List.filter_map, Function.comp_def]
|
||
have (x : { x // x ∈ keys tl }) : (k == x.val) = False := eq_false <| by
|
||
intro h
|
||
rw [containsKey_congr h, mem_keys_iff_contains.mp x.2] at hl
|
||
contradiction
|
||
simp only [this, ↓reduceDIte]
|
||
split
|
||
· simp only [keys_cons, ih, List.unattach, List.map_cons, List.map_map, Function.comp_def]
|
||
· simp only [ih, List.unattach, List.map_map, Function.comp_def]
|
||
|
||
theorem Const.keys_filter [BEq α] [EquivBEq α] {β : Type v}
|
||
{l : List ((_ : α) × β)} {f : α → β → Bool} (hl : DistinctKeys l) :
|
||
(keys (l.filter (fun x => f x.1 x.2))) =
|
||
(List.filter (fun x => f x.1 (getValue x.1 l (containsKey_of_mem_keys x.2)))
|
||
(keys l).attach).unattach := by
|
||
induction l using assoc_induction with
|
||
| nil => simp [keys]
|
||
| cons k v tl ih =>
|
||
rw [List.filter_cons]
|
||
specialize ih hl.tail
|
||
replace hl := hl.containsKey_eq_false
|
||
simp only [keys, List.attach_cons, getValue_cons, ↓reduceDIte,
|
||
List.filter_cons, BEq.rfl, List.filter_map, Function.comp_def]
|
||
have (x : { x // x ∈ keys tl }) : (k == x.val) = False := eq_false <| by
|
||
intro h
|
||
rw [containsKey_congr h, containsKey_of_mem_keys x.2] at hl
|
||
contradiction
|
||
simp only [this, ↓reduceDIte]
|
||
split
|
||
· simp only [keys_cons, ih, List.unattach, List.map_cons, List.map_map, Function.comp_def]
|
||
· simp only [ih, List.unattach, List.map_map, Function.comp_def]
|
||
|
||
@[simp]
|
||
theorem keys_map {l : List ((a : α) × β a)} {f : (a : α) → β a → γ a} :
|
||
keys (l.map fun p => ⟨p.1, f p.1 p.2⟩) = keys l := by
|
||
induction l using assoc_induction <;> simp_all
|
||
|
||
theorem DistinctKeys.filterMap [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{f : (a : α) → β a → Option (γ a)} :
|
||
DistinctKeys l → DistinctKeys (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩)) := by
|
||
apply distinctKeys_of_sublist_keys
|
||
rw [keys_filterMap', keys_eq_map, keys_eq_map]
|
||
apply Sublist.map
|
||
exact filter_sublist
|
||
|
||
theorem DistinctKeys.map [BEq α] {l : List ((a : α) × β a)} {f : (a : α) → β a → γ a}
|
||
(h : DistinctKeys l) : DistinctKeys (l.map fun p => ⟨p.1, f p.1 p.2⟩) :=
|
||
h.of_keys_eq keys_map.symm
|
||
|
||
theorem DistinctKeys.filter [BEq α] {l : List ((a : α) × β a)} {f : (a : α) → β a → Bool}
|
||
(h : DistinctKeys l) : DistinctKeys (l.filter fun p => f p.1 p.2) :=
|
||
distinctKeys_of_sublist filter_sublist h
|
||
|
||
section
|
||
|
||
variable {β : Type v}
|
||
|
||
theorem getValue?_eraseKey_self [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)} {k : α}
|
||
(h : DistinctKeys l) : getValue? k (eraseKey k l) = none := by
|
||
simp [getValue?_eq_getEntry?, getEntry?_eraseKey_self h]
|
||
|
||
theorem getValue?_eraseKey_of_beq [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)} {k a : α}
|
||
(hl : DistinctKeys l) (hka : k == a) : getValue? a (eraseKey k l) = none := by
|
||
simp [getValue?_eq_getEntry?, getEntry?_eraseKey_of_beq hl hka]
|
||
|
||
theorem getValue?_eraseKey_of_false [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)} {k a : α}
|
||
(hka : (k == a) = false) : getValue? a (eraseKey k l) = getValue? a l := by
|
||
simp [getValue?_eq_getEntry?, getEntry?_eraseKey_of_false hka]
|
||
|
||
theorem getValue?_eraseKey [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)} {k a : α}
|
||
(hl : DistinctKeys l) :
|
||
getValue? a (eraseKey k l) = if k == a then none else getValue? a l := by
|
||
simp [getValue?_eq_getEntry?, getEntry?_eraseKey hl, apply_ite (Option.map _)]
|
||
|
||
end
|
||
|
||
theorem getKey?_eraseKey [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
(hl : DistinctKeys l) :
|
||
getKey? a (eraseKey k l) = if k == a then none else getKey? a l := by
|
||
rw [getKey?_eq_getEntry?, getEntry?_eraseKey hl]
|
||
by_cases h : k == a
|
||
. simp [h]
|
||
. simp [h, getKey?_eq_getEntry?]
|
||
|
||
theorem getKey?_eraseKey_self [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
(hl : DistinctKeys l) : getKey? k (eraseKey k l) = none := by
|
||
simp [getKey?_eq_getEntry?, getEntry?_eraseKey_self hl]
|
||
|
||
theorem getKey!_eraseKey [BEq α] [PartialEquivBEq α] [Inhabited α] {l : List ((a : α) × β a)}
|
||
{k a : α} (hl : DistinctKeys l) :
|
||
getKey! a (eraseKey k l) = if k == a then default else getKey! a l := by
|
||
simp [getKey!_eq_getKey?, getKey?_eraseKey hl, apply_ite Option.get!]
|
||
|
||
theorem getKey!_eraseKey_self [BEq α] [PartialEquivBEq α] [Inhabited α] {l : List ((a : α) × β a)}
|
||
{k : α} (hl : DistinctKeys l) : getKey! k (eraseKey k l) = default := by
|
||
simp [getKey!_eq_getKey?, getKey?_eraseKey_self hl]
|
||
|
||
theorem getKeyD_eraseKey [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k a fallback : α}
|
||
(hl : DistinctKeys l) :
|
||
getKeyD a (eraseKey k l) fallback = if k == a then fallback else getKeyD a l fallback := by
|
||
simp [getKeyD_eq_getKey?, getKey?_eraseKey hl, apply_ite (fun x => Option.getD x fallback)]
|
||
|
||
theorem getKeyD_eraseKey_self [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{k fallback : α} (hl : DistinctKeys l) : getKeyD k (eraseKey k l) fallback = fallback := by
|
||
simp [getKeyD_eq_getKey?, getKey?_eraseKey_self hl]
|
||
|
||
theorem containsKey_eraseKey_self [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
(h : DistinctKeys l) : containsKey k (eraseKey k l) = false := by
|
||
simp [containsKey_eq_isSome_getEntry?, getEntry?_eraseKey_self h]
|
||
|
||
theorem containsKey_eraseKey_of_beq [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{k a : α} (hl : DistinctKeys l) (hka : a == k) : containsKey a (eraseKey k l) = false := by
|
||
rw [containsKey_congr hka, containsKey_eraseKey_self hl]
|
||
|
||
theorem containsKey_eraseKey_of_false [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{k a : α} (hka : (k == a) = false) : containsKey a (eraseKey k l) = containsKey a l := by
|
||
simp [containsKey_eq_isSome_getEntry?, getEntry?_eraseKey_of_false hka]
|
||
|
||
theorem containsKey_eraseKey [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
(hl : DistinctKeys l) : containsKey a (eraseKey k l) = (!(k == a) && containsKey a l) := by
|
||
simp [containsKey_eq_isSome_getEntry?, getEntry?_eraseKey hl, apply_ite]
|
||
|
||
theorem isEmpty_eq_isEmpty_eraseKey_and_not_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (k : α) :
|
||
l.isEmpty = ((eraseKey k l).isEmpty && !(containsKey k l)) := by
|
||
rw [Bool.eq_iff_iff, Bool.and_eq_true, Bool.not_eq_true']
|
||
simp only [isEmpty_iff_forall_containsKey, containsKey_eraseKey hd, Bool.and_eq_false_iff,
|
||
Bool.not_eq_false']
|
||
constructor
|
||
· exact fun h => ⟨fun a => Or.inr (h a), h k⟩
|
||
· rintro ⟨h₁, h₂⟩ a
|
||
specialize h₁ a
|
||
cases hbeq : k == a
|
||
· simp_all
|
||
· simp only [hbeq, true_or] at h₁
|
||
exact containsKey_congr hbeq ▸ h₂
|
||
|
||
theorem isEmpty_eq_false_of_isEmpty_eraseKey_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k : α}
|
||
(he : (eraseKey k l).isEmpty = false) :
|
||
l.isEmpty = false := by
|
||
simp_all [isEmpty_eq_isEmpty_eraseKey_and_not_containsKey hd k]
|
||
|
||
theorem getValueCast?_eraseKey [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
(hl : DistinctKeys l) :
|
||
getValueCast? a (eraseKey k l) = if k == a then none else getValueCast? a l := by
|
||
simp only [getValueCast?_eq_getEntry?, getEntry?_eraseKey hl]
|
||
by_cases h : k == a
|
||
· simp only [if_pos h, Option.dmap_none]
|
||
· simp only [if_neg h]
|
||
|
||
theorem getValueCast?_eraseKey_self [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
(hl : DistinctKeys l) : getValueCast? k (eraseKey k l) = none := by
|
||
rw [getValueCast?_eraseKey hl, if_pos BEq.rfl]
|
||
|
||
theorem getValueCast!_eraseKey [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
[Inhabited (β a)] (hl : DistinctKeys l) :
|
||
getValueCast! a (eraseKey k l) = if k == a then default else getValueCast! a l := by
|
||
simp [getValueCast!_eq_getValueCast?, getValueCast?_eraseKey hl, apply_ite Option.get!]
|
||
|
||
theorem getValueCast!_eraseKey_self [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
[Inhabited (β k)] (hl : DistinctKeys l) : getValueCast! k (eraseKey k l) = default := by
|
||
simp [getValueCast!_eq_getValueCast?, getValueCast?_eraseKey_self hl]
|
||
|
||
theorem getValueCastD_eraseKey [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α}
|
||
{fallback : β a} (hl : DistinctKeys l) : getValueCastD a (eraseKey k l) fallback =
|
||
if k == a then fallback else getValueCastD a l fallback := by
|
||
simp [getValueCastD_eq_getValueCast?, getValueCast?_eraseKey hl,
|
||
apply_ite (fun x => Option.getD x fallback)]
|
||
|
||
theorem getValueCastD_eraseKey_self [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k : α}
|
||
{fallback : β k} (hl : DistinctKeys l) :
|
||
getValueCastD k (eraseKey k l) fallback = fallback := by
|
||
simp [getValueCastD_eq_getValueCast?, getValueCast?_eraseKey_self hl]
|
||
|
||
theorem getValue!_eraseKey {β : Type v} [BEq α] [PartialEquivBEq α] [Inhabited β]
|
||
{l : List ((_ : α) × β)} {k a : α} (hl : DistinctKeys l) :
|
||
getValue! a (eraseKey k l) = if k == a then default else getValue! a l := by
|
||
simp [getValue!_eq_getValue?, getValue?_eraseKey hl, apply_ite Option.get!]
|
||
|
||
theorem getValue!_eraseKey_self {β : Type v} [BEq α] [PartialEquivBEq α] [Inhabited β]
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l) :
|
||
getValue! k (eraseKey k l) = default := by
|
||
simp [getValue!_eq_getValue?, getValue?_eraseKey_self hl]
|
||
|
||
theorem getValueD_eraseKey {β : Type v} [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)}
|
||
{k a : α} {fallback : β} (hl : DistinctKeys l) : getValueD a (eraseKey k l) fallback =
|
||
if k == a then fallback else getValueD a l fallback := by
|
||
simp [getValueD_eq_getValue?, getValue?_eraseKey hl, apply_ite (fun x => Option.getD x fallback)]
|
||
|
||
theorem getValueD_eraseKey_self {β : Type v} [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)}
|
||
{k : α} {fallback : β} (hl : DistinctKeys l) :
|
||
getValueD k (eraseKey k l) fallback = fallback := by
|
||
simp [getValueD_eq_getValue?, getValue?_eraseKey_self hl]
|
||
|
||
theorem containsKey_of_containsKey_eraseKey [BEq α] [PartialEquivBEq α] {l : List ((a : α) × β a)}
|
||
{k a : α} (hl : DistinctKeys l) : containsKey a (eraseKey k l) → containsKey a l := by
|
||
simp [containsKey_eraseKey hl]
|
||
|
||
theorem getValueCast_eraseKey [BEq α] [LawfulBEq α] {l : List ((a : α) × β a)} {k a : α} {h}
|
||
(hl : DistinctKeys l) : getValueCast a (eraseKey k l) h =
|
||
getValueCast a l (containsKey_of_containsKey_eraseKey hl h) := by
|
||
rw [containsKey_eraseKey hl, Bool.and_eq_true, Bool.not_eq_true'] at h
|
||
rw [← Option.some_inj, ← getValueCast?_eq_some_getValueCast, getValueCast?_eraseKey hl, h.1]
|
||
simp [← getValueCast?_eq_some_getValueCast]
|
||
|
||
theorem getValue_eraseKey {β : Type v} [BEq α] [PartialEquivBEq α] {l : List ((_ : α) × β)}
|
||
{k a : α} {h} (hl : DistinctKeys l) :
|
||
getValue a (eraseKey k l) h = getValue a l (containsKey_of_containsKey_eraseKey hl h) := by
|
||
rw [containsKey_eraseKey hl, Bool.and_eq_true, Bool.not_eq_true'] at h
|
||
rw [← Option.some_inj, ← getValue?_eq_some_getValue, getValue?_eraseKey hl, h.1]
|
||
simp [← getValue?_eq_some_getValue]
|
||
|
||
theorem getKey_eraseKey [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} {k a : α} {h}
|
||
(hl : DistinctKeys l) : getKey a (eraseKey k l) h =
|
||
getKey a l (containsKey_of_containsKey_eraseKey hl h) := by
|
||
rw [containsKey_eraseKey hl, Bool.and_eq_true, Bool.not_eq_true'] at h
|
||
rw [← Option.some_inj, ← getKey?_eq_some_getKey, getKey?_eraseKey hl, h.1]
|
||
simp [← getKey?_eq_some_getKey]
|
||
|
||
theorem getEntry?_of_perm [BEq α] [PartialEquivBEq α] {l l' : List ((a : α) × β a)} {a : α}
|
||
(hl : DistinctKeys l) (h : Perm l l') : getEntry? a l = getEntry? a l' := by
|
||
induction h
|
||
· simp
|
||
next p t₁ t₂ _ ih₂ =>
|
||
rcases p with ⟨k', v'⟩
|
||
simp only [getEntry?_cons, ih₂ hl.tail]
|
||
next p p' _ =>
|
||
rcases p with ⟨k₁, v₁⟩
|
||
rcases p' with ⟨k₂, v₂⟩
|
||
simp only [getEntry?_cons]
|
||
cases h₂ : k₂ == a <;> cases h₁ : k₁ == a <;> try simp; done
|
||
simp only [distinctKeys_cons_iff, containsKey_cons, Bool.or_eq_false_iff] at hl
|
||
exact ((Bool.eq_false_iff.1 hl.2.1).elim (BEq.trans h₁ (BEq.symm h₂))).elim
|
||
next l₁ l₂ l₃ hl₁₂ _ ih₁ ih₂ => exact (ih₁ hl).trans (ih₂ (hl.perm (hl₁₂.symm)))
|
||
|
||
theorem containsKey_of_perm [BEq α] [PartialEquivBEq α] {l l' : List ((a : α) × β a)} {k : α}
|
||
(h : Perm l l') : containsKey k l = containsKey k l' := by
|
||
induction h
|
||
· simp
|
||
next p t₁ t₂ _ ih₂ => rw [containsKey_cons, containsKey_cons, ih₂]
|
||
next p p' _ =>
|
||
rw [containsKey_cons, containsKey_cons, containsKey_cons, containsKey_cons]
|
||
simp only [← Bool.or_assoc, Bool.or_comm]
|
||
next _ _ _ _ _ ih₁ ih₂ => exact ih₁.trans ih₂
|
||
|
||
theorem getValueCast?_of_perm [BEq α] [LawfulBEq α] {l l' : List ((a : α) × β a)} {a : α}
|
||
(hl : DistinctKeys l) (h : Perm l l') : getValueCast? a l = getValueCast? a l' := by
|
||
simp only [getValueCast?_eq_getEntry?, getEntry?_of_perm hl h]
|
||
|
||
theorem getValueCast_of_perm [BEq α] [LawfulBEq α] {l l' : List ((a : α) × β a)} {a : α} {h'}
|
||
(hl : DistinctKeys l) (h : Perm l l') :
|
||
getValueCast a l h' = getValueCast a l' ((containsKey_of_perm h).symm.trans h') := by
|
||
rw [← Option.some_inj, ← getValueCast?_eq_some_getValueCast, ← getValueCast?_eq_some_getValueCast,
|
||
getValueCast?_of_perm hl h]
|
||
|
||
theorem getValueCast!_of_perm [BEq α] [LawfulBEq α] {l l' : List ((a : α) × β a)} {a : α}
|
||
[Inhabited (β a)] (hl : DistinctKeys l) (h : Perm l l') :
|
||
getValueCast! a l = getValueCast! a l' := by
|
||
simp only [getValueCast!_eq_getValueCast?, getValueCast?_of_perm hl h]
|
||
|
||
theorem getValueCastD_of_perm [BEq α] [LawfulBEq α] {l l' : List ((a : α) × β a)} {a : α}
|
||
{fallback : β a} (hl : DistinctKeys l) (h : Perm l l') :
|
||
getValueCastD a l fallback = getValueCastD a l' fallback := by
|
||
simp only [getValueCastD_eq_getValueCast?, getValueCast?_of_perm hl h]
|
||
|
||
section
|
||
|
||
variable {β : Type v}
|
||
|
||
theorem getValue?_of_perm [BEq α] [PartialEquivBEq α] {l l' : List ((_ : α) × β)} {a : α}
|
||
(hl : DistinctKeys l) (h : Perm l l') : getValue? a l = getValue? a l' := by
|
||
simp only [getValue?_eq_getEntry?, getEntry?_of_perm hl h]
|
||
|
||
theorem getValue_of_perm [BEq α] [PartialEquivBEq α] {l l' : List ((_ : α) × β)} {a : α} {h'}
|
||
(hl : DistinctKeys l) (h : Perm l l') :
|
||
getValue a l h' = getValue a l' ((containsKey_of_perm h).symm.trans h') := by
|
||
rw [← Option.some_inj, ← getValue?_eq_some_getValue, ← getValue?_eq_some_getValue,
|
||
getValue?_of_perm hl h]
|
||
|
||
theorem getValue!_of_perm [BEq α] [PartialEquivBEq α] [Inhabited β] {l l' : List ((_ : α) × β)}
|
||
{a : α} (hl : DistinctKeys l) (h : Perm l l') : getValue! a l = getValue! a l' := by
|
||
simp only [getValue!_eq_getValue?, getValue?_of_perm hl h]
|
||
|
||
theorem getValueD_of_perm [BEq α] [PartialEquivBEq α] {l l' : List ((_ : α) × β)} {a : α}
|
||
{fallback : β} (hl : DistinctKeys l) (h : Perm l l') :
|
||
getValueD a l fallback = getValueD a l' fallback := by
|
||
simp only [getValueD_eq_getValue?, getValue?_of_perm hl h]
|
||
|
||
end
|
||
|
||
theorem getKey?_of_perm [BEq α] [PartialEquivBEq α] {l l' : List ((a : α) × β a)} {a : α}
|
||
(hl : DistinctKeys l) (h : Perm l l') : getKey? a l = getKey? a l' := by
|
||
rw [getKey?_eq_getEntry?, getKey?_eq_getEntry?, getEntry?_of_perm hl h]
|
||
|
||
theorem getKey_of_perm [BEq α] [PartialEquivBEq α] {l l' : List ((a : α) × β a)} {a : α} {h'}
|
||
(hl : DistinctKeys l) (h : Perm l l') :
|
||
getKey a l h' = getKey a l' ((containsKey_of_perm h).symm.trans h') := by
|
||
rw [← Option.some_inj, ← getKey?_eq_some_getKey, ← getKey?_eq_some_getKey,
|
||
getKey?_of_perm hl h]
|
||
|
||
theorem getKey!_of_perm [BEq α] [PartialEquivBEq α] [Inhabited α] {l l' : List ((a : α) × β a)}
|
||
{a : α} (hl : DistinctKeys l) (h : Perm l l') :
|
||
getKey! a l = getKey! a l' := by
|
||
simp only [getKey!_eq_getKey?, getKey?_of_perm hl h]
|
||
|
||
theorem getKeyD_of_perm [BEq α] [PartialEquivBEq α] {l l' : List ((a : α) × β a)} {a fallback : α}
|
||
(hl : DistinctKeys l) (h : Perm l l') :
|
||
getKeyD a l fallback = getKeyD a l' fallback := by
|
||
simp only [getKeyD_eq_getKey?, getKey?_of_perm hl h]
|
||
|
||
theorem perm_cons_getEntry [BEq α] {l : List ((a : α) × β a)} {a : α} (h : containsKey a l) :
|
||
∃ l', Perm l (getEntry a l h :: l') := by
|
||
induction l using assoc_induction
|
||
· simp at h
|
||
next k' v' t ih =>
|
||
simp only [containsKey_cons, Bool.or_eq_true] at h
|
||
cases hk : k' == a
|
||
· obtain ⟨l', hl'⟩ := ih (h.resolve_left (Bool.not_eq_true _ ▸ hk))
|
||
rw [getEntry_cons_of_false hk]
|
||
exact ⟨⟨k', v'⟩ :: l', (hl'.cons _).trans (Perm.swap' _ _ (Perm.refl _))⟩
|
||
· exact ⟨t, by rw [getEntry_cons_of_beq hk]⟩
|
||
|
||
-- Note: this theorem becomes false if you don't assume that BEq is reflexive on α.
|
||
theorem getEntry?_ext [BEq α] [EquivBEq α] {l l' : List ((a : α) × β a)} (hl : DistinctKeys l)
|
||
(hl' : DistinctKeys l') (h : ∀ a, getEntry? a l = getEntry? a l') : Perm l l' := by
|
||
induction l using assoc_induction generalizing l'
|
||
· induction l' using assoc_induction
|
||
· exact Perm.refl _
|
||
next k _ _ _ => simpa using h k
|
||
next k v t ih =>
|
||
have hl'k₁ : getEntry? k l' = some ⟨k, v⟩ := by rw [← h, getEntry?_cons_self]
|
||
have hl'k₂ : containsKey k l' := by
|
||
rw [containsKey_eq_isSome_getEntry?, hl'k₁, Option.isSome_some]
|
||
obtain ⟨l'', hl''⟩ := perm_cons_getEntry hl'k₂
|
||
rw [getEntry_eq_of_getEntry?_eq_some hl'k₁] at hl''
|
||
suffices Perm t l'' from (this.cons _).trans hl''.symm
|
||
apply ih hl.tail (hl'.perm hl''.symm).tail
|
||
intro k'
|
||
cases hk' : k == k'
|
||
· simpa only [getEntry?_of_perm hl' hl'', getEntry?_cons_of_false hk'] using h k'
|
||
· rw [← getEntry?_congr hk', ← getEntry?_congr hk', getEntry?_eq_none.2 hl.containsKey_eq_false,
|
||
getEntry?_eq_none.2 (hl'.perm hl''.symm).containsKey_eq_false]
|
||
|
||
theorem getValueCast?_ext [BEq α] [LawfulBEq α] {l l' : List ((a : α) × β a)} (hl : DistinctKeys l)
|
||
(hl' : DistinctKeys l') (h : ∀ a, getValueCast? a l = getValueCast? a l') : Perm l l' := by
|
||
apply getEntry?_ext hl hl'
|
||
intro a
|
||
simp only [getEntry?_eq_getValueCast?, h]
|
||
|
||
theorem getKey_getValue?_ext [BEq α] [EquivBEq α] {β : Type v}
|
||
{l l' : List ((_ : α) × β)} (hl : DistinctKeys l) (hl' : DistinctKeys l')
|
||
(hk : ∀ a h h', getKey a l h = getKey a l' h') (hv : ∀ a, getValue? a l = getValue? a l') :
|
||
Perm l l' := by
|
||
apply getEntry?_ext hl hl'
|
||
intro a
|
||
specialize hk a; specialize hv a
|
||
by_cases h' : containsKey a l'
|
||
· simp only [getValue?_eq_some_getValue h'] at hv
|
||
have h'' := containsKey_eq_isSome_getValue?.trans (hv ▸ rfl : (getValue? a l).isSome = true)
|
||
specialize hk h'' h'
|
||
simp only [getEntry?_eq_some_getEntry, h', h'', getEntry_eq_getKey_getValue]
|
||
simp only [getValue?_eq_some_getValue h'', Option.some.injEq] at hv
|
||
rw [hk, hv]
|
||
· simp only [getValue?_eq_none.mpr, h'] at hv
|
||
have h'' := containsKey_eq_isSome_getValue?.trans (hv ▸ rfl : (getValue? a l).isSome = false)
|
||
simp only [getEntry?_eq_none.mpr, h', h'']
|
||
|
||
theorem getKey?_getValue?_ext [BEq α] [EquivBEq α] {β : Type v}
|
||
{l l' : List ((_ : α) × β)} (hl : DistinctKeys l) (hl' : DistinctKeys l')
|
||
(hk : ∀ a, getKey? a l = getKey? a l') (hv : ∀ a, getValue? a l = getValue? a l') :
|
||
Perm l l' := by
|
||
refine getKey_getValue?_ext hl hl' ?_ hv
|
||
intro a ha ha'
|
||
simp only [getKey, hk]
|
||
|
||
theorem getKey?_ext [BEq α] [EquivBEq α]
|
||
{l l' : List ((_ : α) × Unit)} (hl : DistinctKeys l) (hl' : DistinctKeys l')
|
||
(h : ∀ a, getKey? a l = getKey? a l') : Perm l l' := by
|
||
apply getKey?_getValue?_ext hl hl' h
|
||
intro a
|
||
specialize h a
|
||
by_cases h' : containsKey a l'
|
||
· rw [getKey?_eq_some_getKey h'] at h
|
||
have h'' := containsKey_eq_isSome_getKey?.trans (h ▸ Option.isSome_some)
|
||
simp only [getValue?_eq_some_getValue, h', h'']
|
||
· rw [getKey?_eq_none ((Bool.not_eq_true _).mp h')] at h
|
||
have h'' := containsKey_eq_isSome_getKey?.trans (h ▸ Option.isSome_none)
|
||
simp only [getValue?_eq_none.mpr, h', h'']
|
||
|
||
theorem containsKey_ext [BEq α] [LawfulBEq α]
|
||
{l l' : List ((_ : α) × Unit)} (hl : DistinctKeys l) (hl' : DistinctKeys l')
|
||
(h : ∀ a, containsKey a l = containsKey a l') : Perm l l' := by
|
||
apply getKey?_ext hl hl'
|
||
intro a
|
||
by_cases h' : containsKey a l'
|
||
· simp only [getKey?_eq_some, h', (h a).trans h']
|
||
· simp only [getKey?_eq_none, h', (h a).trans ((Bool.not_eq_true _).mp h')]
|
||
|
||
theorem replaceEntry_of_perm [BEq α] [EquivBEq α] {l l' : List ((a : α) × β a)} {k : α} {v : β k}
|
||
(hl : DistinctKeys l) (h : Perm l l') : Perm (replaceEntry k v l) (replaceEntry k v l') := by
|
||
apply getEntry?_ext hl.replaceEntry (hl.perm h.symm).replaceEntry
|
||
simp [getEntry?_replaceEntry, getEntry?_of_perm hl h, containsKey_of_perm h]
|
||
|
||
theorem insertEntry_of_perm [BEq α] [EquivBEq α] {l l' : List ((a : α) × β a)} {k : α} {v : β k}
|
||
(hl : DistinctKeys l) (h : Perm l l') : Perm (insertEntry k v l) (insertEntry k v l') := by
|
||
apply getEntry?_ext hl.insertEntry (hl.perm h.symm).insertEntry
|
||
simp [getEntry?_insertEntry, getEntry?_of_perm hl h]
|
||
|
||
theorem insertEntryIfNew_of_perm [BEq α] [EquivBEq α] {l l' : List ((a : α) × β a)}
|
||
{k : α} {v : β k} (hl : DistinctKeys l) (h : Perm l l') :
|
||
Perm (insertEntryIfNew k v l) (insertEntryIfNew k v l') := by
|
||
apply getEntry?_ext hl.insertEntryIfNew (hl.perm h.symm).insertEntryIfNew
|
||
simp [getEntry?_insertEntryIfNew, getEntry?_of_perm hl h, containsKey_of_perm h]
|
||
|
||
theorem eraseKey_of_perm [BEq α] [EquivBEq α] {l l' : List ((a : α) × β a)} {k : α}
|
||
(hl : DistinctKeys l) (h : Perm l l') : Perm (eraseKey k l) (eraseKey k l') := by
|
||
apply getEntry?_ext hl.eraseKey (hl.perm h.symm).eraseKey
|
||
simp [getEntry?_eraseKey hl, getEntry?_eraseKey (hl.perm h.symm), getEntry?_of_perm hl h]
|
||
|
||
@[simp]
|
||
theorem getEntry?_append [BEq α] {l l' : List ((a : α) × β a)} {a : α} :
|
||
getEntry? a (l ++ l') = (getEntry? a l).or (getEntry? a l') := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k' v' t ih => cases h : k' == a <;> simp_all [getEntry?_cons]
|
||
|
||
theorem getEntry?_append_of_containsKey_eq_false [BEq α] {l l' : List ((a : α) × β a)} {a : α}
|
||
(h : containsKey a l' = false) : getEntry? a (l ++ l') = getEntry? a l := by
|
||
rw [getEntry?_append, getEntry?_eq_none.2 h, Option.or_none]
|
||
|
||
@[simp]
|
||
theorem containsKey_append [BEq α] {l l' : List ((a : α) × β a)} {a : α} :
|
||
containsKey a (l ++ l') = (containsKey a l || containsKey a l') := by
|
||
simp [containsKey_eq_isSome_getEntry?]
|
||
|
||
theorem containsKey_flatMap_eq_false [BEq α] {γ : Type w} {l : List γ} {f : γ → List ((a : α) × β a)}
|
||
{a : α} (h : ∀ (i : Nat) (h : i < l.length), containsKey a (f l[i]) = false) :
|
||
containsKey a (l.flatMap f) = false := by
|
||
induction l
|
||
· simp
|
||
next g t ih =>
|
||
simp only [List.flatMap_cons, containsKey_append, Bool.or_eq_false_iff]
|
||
refine ⟨?_, ?_⟩
|
||
· simpa using h 0 (by simp)
|
||
· refine ih ?_
|
||
intro i hi
|
||
simpa using h (i + 1) (by simp only [List.length_cons]; omega)
|
||
|
||
theorem containsKey_append_of_not_contains_right [BEq α] {l l' : List ((a : α) × β a)} {a : α}
|
||
(hl' : containsKey a l' = false) : containsKey a (l ++ l') = containsKey a l := by
|
||
simp [hl']
|
||
|
||
@[simp]
|
||
theorem getValue?_append {β : Type v} [BEq α] {l l' : List ((_ : α) × β)} {a : α} :
|
||
getValue? a (l ++ l') = (getValue? a l).or (getValue? a l') := by
|
||
simp [getValue?_eq_getEntry?, Option.map_or]
|
||
|
||
theorem getValue?_append_of_containsKey_eq_false {β : Type v} [BEq α] {l l' : List ((_ : α) × β)}
|
||
{a : α} (h : containsKey a l' = false) : getValue? a (l ++ l') = getValue? a l := by
|
||
rw [getValue?_append, getValue?_eq_none.2 h, Option.or_none]
|
||
|
||
theorem getValue_append_of_containsKey_eq_false {β : Type v} [BEq α] {l l' : List ((_ : α) × β)}
|
||
{a : α} {h'} (h : containsKey a l' = false) : getValue a (l ++ l') h' =
|
||
getValue a l ((containsKey_append_of_not_contains_right h).symm.trans h') := by
|
||
rw [← Option.some_inj, ← getValue?_eq_some_getValue, ← getValue?_eq_some_getValue,
|
||
getValue?_append_of_containsKey_eq_false h]
|
||
|
||
theorem getValueCast?_append_of_containsKey_eq_false [BEq α] [LawfulBEq α]
|
||
{l l' : List ((a : α) × β a)} {a : α} (hl' : containsKey a l' = false) :
|
||
getValueCast? a (l ++ l') = getValueCast? a l := by
|
||
simp only [getValueCast?_eq_getEntry?, getEntry?_append, getEntry?_eq_none.2 hl', Option.or_none]
|
||
|
||
theorem getValueCast_append_of_containsKey_eq_false [BEq α] [LawfulBEq α]
|
||
{l l' : List ((a : α) × β a)} {a : α} {h} (hl' : containsKey a l' = false) :
|
||
getValueCast a (l ++ l') h =
|
||
getValueCast a l ((containsKey_append_of_not_contains_right hl').symm.trans h) := by
|
||
rw [← Option.some_inj, ← getValueCast?_eq_some_getValueCast, ← getValueCast?_eq_some_getValueCast,
|
||
getValueCast?_append_of_containsKey_eq_false hl']
|
||
|
||
theorem getKey?_append_of_containsKey_eq_false [BEq α] [PartialEquivBEq α]
|
||
{l l' : List ((a : α) × β a)} {a : α} (hl' : containsKey a l' = false) :
|
||
getKey? a (l ++ l') = getKey? a l := by
|
||
simp [getKey?_eq_getEntry?, getEntry?_eq_none.2 hl']
|
||
|
||
theorem getKey_append_of_containsKey_eq_false [BEq α] [PartialEquivBEq α]
|
||
{l l' : List ((a : α) × β a)} {a : α} {h} (hl' : containsKey a l' = false) :
|
||
getKey a (l ++ l') h =
|
||
getKey a l ((containsKey_append_of_not_contains_right hl').symm.trans h) := by
|
||
rw [← Option.some_inj, ← getKey?_eq_some_getKey, ← getKey?_eq_some_getKey,
|
||
getKey?_append_of_containsKey_eq_false hl']
|
||
|
||
theorem replaceEntry_append_of_containsKey_left [BEq α] {l l' : List ((a : α) × β a)} {k : α}
|
||
{v : β k} (h : containsKey k l) : replaceEntry k v (l ++ l') = replaceEntry k v l ++ l' := by
|
||
induction l using assoc_induction
|
||
· simp at h
|
||
next k' v' t ih =>
|
||
simp only [containsKey_cons, Bool.or_eq_true] at h
|
||
cases h' : k' == k
|
||
· simpa [replaceEntry_cons, h'] using ih (h.resolve_left (Bool.not_eq_true _ ▸ h'))
|
||
· simp [replaceEntry_cons, h']
|
||
|
||
theorem replaceEntry_append_of_containsKey_left_eq_false [BEq α] {l l' : List ((a : α) × β a)}
|
||
{k : α} {v : β k} (h : containsKey k l = false) :
|
||
replaceEntry k v (l ++ l') = l ++ replaceEntry k v l' := by
|
||
induction l using assoc_induction
|
||
· simp
|
||
next k' v' t ih =>
|
||
simp only [containsKey_cons, Bool.or_eq_false_iff] at h
|
||
simpa [replaceEntry_cons, h.1] using ih h.2
|
||
|
||
theorem replaceEntry_append_of_containsKey_right_eq_false [BEq α] {l l' : List ((a : α) × β a)}
|
||
{k : α} {v : β k} (h : containsKey k l' = false) :
|
||
replaceEntry k v (l ++ l') = replaceEntry k v l ++ l' := by
|
||
cases h' : containsKey k l
|
||
· rw [replaceEntry_of_containsKey_eq_false, replaceEntry_of_containsKey_eq_false h']
|
||
simpa using ⟨h', h⟩
|
||
· rw [replaceEntry_append_of_containsKey_left h']
|
||
|
||
theorem insertEntry_append_of_not_contains_right [BEq α] {l l' : List ((a : α) × β a)}
|
||
{k : α} {v : β k} (h' : containsKey k l' = false) :
|
||
insertEntry k v (l ++ l') = insertEntry k v l ++ l' := by
|
||
cases h : containsKey k l
|
||
· simp [insertEntry, containsKey_append, h, h']
|
||
· simp [insertEntry, containsKey_append, h, h', replaceEntry_append_of_containsKey_left h]
|
||
|
||
theorem eraseKey_append_of_containsKey_right_eq_false [BEq α] {l l' : List ((a : α) × β a)} {k : α}
|
||
(h : containsKey k l' = false) : eraseKey k (l ++ l') = eraseKey k l ++ l' := by
|
||
induction l using assoc_induction
|
||
· simp [eraseKey_of_containsKey_eq_false h]
|
||
next k' v' t ih =>
|
||
rw [List.cons_append, eraseKey_cons, eraseKey_cons]
|
||
cases k' == k
|
||
· rw [cond_false, cond_false, ih, List.cons_append]
|
||
· rw [cond_true, cond_true]
|
||
|
||
theorem mem_iff_getValueCast?_eq_some [BEq α] [LawfulBEq α] {k : α} {v : β k}
|
||
{l : List ((a : α) × β a)} (h : DistinctKeys l) :
|
||
⟨k, v⟩ ∈ l ↔ getValueCast? k l = some v := by
|
||
rw [mem_iff_getEntry?_eq_some h, getValueCast?_eq_getEntry?, Option.dmap_eq_some]
|
||
refine ⟨?_, ?_⟩
|
||
· intro hkv
|
||
refine ⟨⟨k, v⟩, hkv, by simp⟩
|
||
· rintro ⟨⟨k', v'⟩, hkv, hkv'⟩
|
||
obtain rfl := beq_iff_eq.1 (beq_of_getEntry?_eq_some hkv)
|
||
simpa [hkv]
|
||
|
||
theorem find?_eq_some_iff_getValueCast?_eq_some [BEq α] [LawfulBEq α]
|
||
{l : List ((a : α) × β a)} {k : α} {v : β k} (h : DistinctKeys l) :
|
||
List.find? (fun x => x.fst == k) l = some ⟨k, v⟩ ↔ getValueCast? k l = some v := by
|
||
rw [← getEntry?_eq_find, ← mem_iff_getEntry?_eq_some (p := ⟨k, v⟩) h,
|
||
← mem_iff_getValueCast?_eq_some h]
|
||
|
||
theorem find?_eq_none_iff_containsKey_eq_false [BEq α] [PartialEquivBEq α]
|
||
{l : List ((a : α) × β a)} {k : α} :
|
||
List.find? (fun x => x.fst == k) l = none ↔ containsKey k l = false := by
|
||
simp [List.find?_eq_none, containsKey_eq_false_iff, BEq.comm]
|
||
|
||
theorem pairwise_fst_eq_false [BEq α] {l : List ((a : α) × β a)} (h : DistinctKeys l) :
|
||
List.Pairwise (fun a b => (a.fst == b.fst) = false) l := by
|
||
rw [DistinctKeys.def] at h
|
||
assumption
|
||
|
||
theorem map_fst_map_toProd_eq_keys {β : Type v} {l : List ((_ : α) × β)} :
|
||
List.map Prod.fst (List.map (fun x => (x.fst, x.snd)) l) = List.keys l := by
|
||
induction l with
|
||
| nil => simp
|
||
| cons hd tl ih =>
|
||
simp only [List.map_cons, keys]
|
||
congr
|
||
|
||
theorem find?_map_eq_none_iff_containsKey_eq_false [BEq α] [PartialEquivBEq α]
|
||
{β : Type v} {l : List ((_ : α) × β)} {k : α} :
|
||
List.find? (fun x => x.fst == k) (l.map (fun x => (x.fst, x.snd))) = none ↔
|
||
containsKey k l = false := by
|
||
simp [List.find?_eq_none, containsKey_eq_false_iff, BEq.comm]
|
||
|
||
theorem mem_map_toProd_iff_mem {β : Type v} {k : α} {v : β} {l : List ((_ : α) × β)} :
|
||
⟨k, v⟩ ∈ l ↔ (k, v) ∈ l.map (fun x => (x.fst, x.snd)) := by
|
||
simp only [List.mem_map, Prod.mk.injEq]
|
||
constructor
|
||
· intro h
|
||
exists ⟨k, v⟩
|
||
· intro h
|
||
rcases h with ⟨a, a_l, a_k, a_v⟩
|
||
simp [← a_k, ← a_v, a_l]
|
||
|
||
theorem mem_iff_getValue?_eq_some [BEq α] [LawfulBEq α] {β : Type v} {k : α} {v : β}
|
||
{l : List ((_ : α) × β)} (h : DistinctKeys l) :
|
||
⟨k, v⟩ ∈ l ↔ getValue? k l = some v := by
|
||
simp only [mem_iff_getEntry?_eq_some h, getValue?_eq_getEntry?, Option.map_eq_some_iff]
|
||
constructor
|
||
· intro h
|
||
exists ⟨k, v⟩
|
||
· intro h
|
||
rcases h with ⟨a, h, a_v⟩
|
||
simp [h, ← a_v, Sigma.ext_iff]
|
||
apply LawfulBEq.eq_of_beq (beq_of_getEntry?_eq_some h)
|
||
|
||
theorem mem_map_toProd_iff_getValue?_eq_some [BEq α] [LawfulBEq α] {β : Type v} {k : α} {v : β}
|
||
{l : List ((_ : α) × β)} (h : DistinctKeys l) :
|
||
⟨k, v⟩ ∈ l.map (fun x => (x.fst, x.snd)) ↔ getValue? k l = some v := by
|
||
rw [← mem_map_toProd_iff_mem]
|
||
exact mem_iff_getValue?_eq_some h
|
||
|
||
theorem find?_map_toProd_eq_some_iff_getKey?_eq_some_and_getValue?_eq_some [BEq α] [EquivBEq α]
|
||
{β : Type v} {k k': α} {v : β} {l : List ((_ : α) × β)} :
|
||
(l.map (fun x => (x.fst, x.snd))).find? (fun a => a.1 == k) = some (k', v) ↔
|
||
getKey? k l = some k' ∧ getValue? k l = some v := by
|
||
induction l with
|
||
| nil => simp
|
||
| cons hd tl ih =>
|
||
simp only [List.map_cons, List.find?_cons_eq_some, Prod.mk.injEq, Bool.not_eq_eq_eq_not,
|
||
Bool.not_true, getKey?, cond_eq_ite, getValue?]
|
||
by_cases hdfst_k: hd.fst == k
|
||
· simp only [hdfst_k, true_and, Bool.true_eq_false, false_and, or_false, ↓reduceIte,
|
||
Option.some.injEq]
|
||
· simp only [hdfst_k, Bool.false_eq_true, false_and, true_and, false_or, ↓reduceIte]
|
||
rw [ih]
|
||
|
||
theorem mem_iff_getKey?_eq_some_and_getValue?_eq_some [BEq α] [EquivBEq α]
|
||
{β : Type v} {k: α} {v : β} {l : List ((_ : α) × β)} (h : DistinctKeys l) :
|
||
⟨k, v⟩ ∈ l ↔ getKey? k l = some k ∧ getValue? k l = some v := by
|
||
rw [mem_iff_getEntry?_eq_some h, getEntry?_eq_some_iff_getKey?_eq_some_getValue?_eq_some]
|
||
|
||
theorem getValue?_eq_some_iff_exists_beq_and_mem_toList {β : Type v} [BEq α] [EquivBEq α]
|
||
{l : List ((_ : α) × β)} {k: α} {v : β} (h : DistinctKeys l) :
|
||
getValue? k l = some v ↔ ∃ k', (k == k') = true ∧ (k', v) ∈ l.map (fun x => (x.fst, x.snd)) := by
|
||
simp only [getValue?_eq_getEntry?, Option.map_eq_some_iff, ← mem_map_toProd_iff_mem,
|
||
mem_iff_getEntry?_eq_some h]
|
||
constructor
|
||
· intro h'
|
||
rcases h' with ⟨a, h', a_v⟩
|
||
exists a.1
|
||
have k_afst : a.fst == k := beq_of_getEntry?_eq_some h'
|
||
simp [k_afst, getEntry?_congr k_afst, ← a_v, h', BEq.symm]
|
||
· intro h'
|
||
rcases h' with ⟨k', k_k', h'⟩
|
||
exists ⟨k', v⟩
|
||
simp only [and_true, getEntry?_congr k_k', h']
|
||
|
||
|
||
theorem mem_map_toProd_iff_getKey?_eq_some_and_getValue?_eq_some [BEq α] [EquivBEq α]
|
||
{β : Type v} {k: α} {v : β} {l : List ((_ : α) × β)} (h : DistinctKeys l) :
|
||
(k, v) ∈ l.map (fun x => (x.fst, x.snd)) ↔ getKey? k l = some k ∧ getValue? k l = some v := by
|
||
rw [← mem_map_toProd_iff_mem]
|
||
exact mem_iff_getKey?_eq_some_and_getValue?_eq_some h
|
||
|
||
theorem pairwise_fst_eq_false_map_toProd [BEq α] {β : Type v}
|
||
{l : List ((_ : α) × β)} (h : DistinctKeys l) :
|
||
List.Pairwise (fun a b => (a.fst == b.fst) = false) (List.map (fun x => (x.fst, x.snd)) l) := by
|
||
rw [DistinctKeys.def] at h
|
||
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 a.1 a.2 b) init =
|
||
(l.map fun x => (x.1, x.2)).foldrM (fun a b => f a.1 a.2 b) 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 a.1 a.2 b) init =
|
||
(l.map fun x => (x.1, x.2)).foldr (fun a b => f a.1 a.2 b) 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 ((a : α) × β a)} {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 ((a : α) × β a)} {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 [keys, ih]
|
||
|
||
theorem foldrM_eq_foldrM_keys {δ : Type w} {m' : Type w → Type w'} [Monad m'] [LawfulMonad m']
|
||
{l : List ((a : α) × β a)} {f : α → δ → m' δ} {init : δ} :
|
||
l.foldrM (fun a b => f a.1 b) init = (keys l).foldrM f init := by
|
||
induction l generalizing init with
|
||
| nil => simp
|
||
| cons hd tl ih =>
|
||
simp [keys, ih]
|
||
|
||
theorem foldrM_eq_foldrM_keys' {δ : Type w} {m' : Type w → Type w'} [Monad m'] [LawfulMonad m']
|
||
{l : List ((a : α) × β a)} {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 ((a : α) × β a)} {f : α → δ → δ} {init : δ} :
|
||
l.foldr (fun a b => f a.1 b) init = (keys l).foldr f 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 ((a : α) × β a)} {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 ((a : α) × β a)} {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 ((a : α) × β a)} :
|
||
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
|
||
| .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 [List.map_cons, List.contains_cons]
|
||
rw [BEq.comm]
|
||
conv => left; left; rw [Bool.or_comm]
|
||
rw [Bool.or_assoc]
|
||
|
||
theorem containsKey_insertList_disj_of_containsKey [BEq α] [PartialEquivBEq α] {l toInsert : List ((a : α) × β a)}
|
||
{k : α} : containsKey k (List.insertList l toInsert) =
|
||
(containsKey k l || containsKey k toInsert) := by
|
||
rw [@containsKey_eq_contains_map_fst α β _ _ toInsert k]
|
||
simp only [containsKey_insertList, List.contains_map]
|
||
|
||
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?]
|
||
simp only [getEntry?_insertList_of_contains_eq_false not_contains]
|
||
|
||
theorem getValueCast?_insertList_of_mem [BEq α] [LawfulBEq α]
|
||
{l toInsert : List ((a : α) × β a)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' : α} (k_beq : k == k') {v : β k}
|
||
(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
|
||
simp only [this, Option.dmap_some]
|
||
|
||
theorem getValueCast_insertList_of_mem [BEq α] [LawfulBEq α]
|
||
{l toInsert : List ((a : α) × β a)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' : α} (k_beq : k == k') (v : β k)
|
||
(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 distinct_l k_beq 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)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' : α} (k_beq : k == k') (v : β k) [Inhabited (β k')]
|
||
(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 distinct_l k_beq 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)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' : α} (k_beq : k == k') {v : β k} {fallback : β k'}
|
||
(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 distinct_l k_beq 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)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' : α} (k_beq : k == k')
|
||
(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)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' : α} (k_beq : k == k')
|
||
(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 distinct_l k_beq 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)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' : α} (k_beq : k == k')
|
||
(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 distinct_l k_beq 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)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' fallback : α} (k_beq : k == k')
|
||
(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 distinct_l k_beq 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
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def insertListIfNew [BEq α] (l : List ((a : α) × β a)) (toInsert : List ((a : α) × β a)) :
|
||
List ((a : α) × β a) :=
|
||
match toInsert with
|
||
| .nil => l
|
||
| .cons ⟨k, v⟩ tl => insertListIfNew (insertEntryIfNew k v l) tl
|
||
|
||
theorem DistinctKeys.insertListIfNew [BEq α] [PartialEquivBEq α] {l₁ l₂ : List ((a : α) × β a)}
|
||
(h : DistinctKeys l₁) :
|
||
DistinctKeys (insertListIfNew l₁ l₂) := by
|
||
induction l₂ using assoc_induction generalizing l₁
|
||
· simpa [insertListIfNew]
|
||
· rename_i k v t ih
|
||
rw [insertListIfNew.eq_def]
|
||
exact ih h.insertEntryIfNew
|
||
|
||
theorem insertListIfNew_perm_of_perm_first [BEq α] [EquivBEq α] {l1 l2 toInsert : List ((a : α) × β a)}
|
||
(h : Perm l1 l2) (distinct : DistinctKeys l1) :
|
||
Perm (insertListIfNew l1 toInsert) (insertListIfNew l2 toInsert) := by
|
||
induction toInsert generalizing l1 l2 with
|
||
| nil => simp [insertListIfNew, h]
|
||
| cons hd tl ih =>
|
||
simp only [insertListIfNew]
|
||
apply ih (insertEntryIfNew_of_perm distinct h) (DistinctKeys.insertEntryIfNew distinct)
|
||
|
||
theorem containsKey_insertListIfNew [BEq α] [PartialEquivBEq α] {l toInsert : List ((a : α) × β a)}
|
||
{k : α} : containsKey k (List.insertListIfNew l toInsert) =
|
||
(containsKey k l || (toInsert.map Sigma.fst).contains k) := by
|
||
induction toInsert generalizing l with
|
||
| nil => simp only [insertListIfNew, List.map_nil, List.elem_nil, Bool.or_false]
|
||
| cons hd tl ih =>
|
||
unfold insertListIfNew
|
||
rw [ih]
|
||
rw [containsKey_insertEntryIfNew]
|
||
simp only [List.map_cons, List.contains_cons]
|
||
rw [BEq.comm]
|
||
conv => left; left; rw [Bool.or_comm]
|
||
rw [Bool.or_assoc]
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def insertSmallerList [BEq α] (l₁ l₂ : List ((a : α) × β a)) : List ((a : α) × β a) :=
|
||
if l₁.length ≤ l₂.length then insertListIfNew l₂ l₁ else insertList l₁ l₂
|
||
|
||
theorem contains_insertList_iff [BEq α] [EquivBEq α] {l toInsert : List ((a : α) × β a)} {k : α} :
|
||
containsKey k (insertList l toInsert) = true ↔ containsKey k l = true ∨ containsKey k toInsert = true := by
|
||
simp only [containsKey_insertList, Bool.or_eq_true]
|
||
simp only [containsKey_eq_contains_map_fst, List.contains_map, List.any_eq_true]
|
||
|
||
theorem contains_of_contains_insertList_of_contains_eq_false_right [BEq α] [EquivBEq α] {l toInsert : List ((a : α) × β a)} {k : α}
|
||
(h₁ : containsKey k (insertList l toInsert) = true)
|
||
(h₂ : containsKey k toInsert = false) : containsKey k l = true := by
|
||
have := contains_insertList_iff.1 h₁
|
||
simp only [h₂, Bool.false_eq_true, or_false] at this
|
||
exact this
|
||
|
||
theorem contains_of_contains_insertList_of_contains_eq_false_left [BEq α] [EquivBEq α] {l toInsert : List ((a : α) × β a)} {k : α}
|
||
(h₁ : containsKey k (insertList l toInsert) = true)
|
||
(h₂ : containsKey k l = false) : containsKey k toInsert = true := by
|
||
have := contains_insertList_iff.1 h₁
|
||
simpa only [h₂, Bool.false_eq_true, false_or]
|
||
|
||
theorem contains_insertList_of_left [BEq α] [EquivBEq α] {l toInsert : List ((a : α) × β a)} {k : α}
|
||
(contains : containsKey k l = true) : containsKey k (insertList l toInsert) = true := by
|
||
rw [containsKey_insertList, ← containsKey_eq_contains_map_fst]
|
||
simp only [contains, Bool.true_or]
|
||
|
||
theorem contains_insertList_of_right [BEq α] [EquivBEq α] {l toInsert : List ((a : α) × β a)} {k : α}
|
||
(contains : containsKey k toInsert = true) : containsKey k (insertList l toInsert) = true := by
|
||
rw [containsKey_insertList, ← containsKey_eq_contains_map_fst]
|
||
simp only [contains, Bool.or_true]
|
||
|
||
|
||
theorem DistinctKeys_impl_Pairwise_distinct [BEq α] [EquivBEq α] {l : List ((a : α) × β a)} (distinct_l : DistinctKeys l) :
|
||
List.Pairwise (fun a b => (a.fst == b.fst) = false) l := by
|
||
cases distinct_l
|
||
case mk distinct_l =>
|
||
simp only [keys_eq_map] at distinct_l
|
||
apply List.Pairwise.of_map
|
||
case p => exact distinct_l
|
||
simp only [imp_self, implies_true]
|
||
|
||
theorem insertList_perm_of_perm_second [BEq α] [EquivBEq α] {l1 l2 l : List ((a : α) × β a)}
|
||
(h : Perm l1 l2) (distinct_l : DistinctKeys l) (distinct : DistinctKeys l1) :
|
||
Perm (insertList l l1) (insertList l l2) := by
|
||
apply getEntry?_ext
|
||
. apply DistinctKeys.insertList distinct_l
|
||
. apply DistinctKeys.insertList distinct_l
|
||
intro k
|
||
rw [@getEntry?_insertList α β _ _ l l1 distinct_l (DistinctKeys_impl_Pairwise_distinct distinct) k]
|
||
have distinct' := (DistinctKeys.perm (Perm.symm h) distinct)
|
||
rw [@getEntry?_insertList α β _ _ l l2 distinct_l (DistinctKeys_impl_Pairwise_distinct distinct') k]
|
||
rw [@getEntry?_of_perm α β _ _ l1 l2 k distinct h]
|
||
|
||
theorem getEntry?_insertList_of_contains_left_eq_false [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : List.Pairwise (fun a b => (a.fst == b.fst) = false) toInsert)
|
||
(not_contains : containsKey k l = false) :
|
||
getEntry? k (insertList l toInsert) = getEntry? k toInsert := by
|
||
have subgoal : getEntry? k l = none := by
|
||
rwa [containsKey_eq_isSome_getEntry?, ← Bool.not_eq_true, Option.not_isSome_iff_eq_none] at not_contains
|
||
rw [getEntry?_insertList]
|
||
simp only [subgoal, Option.or_none]
|
||
. exact distinct_l
|
||
. exact distinct_toInsert
|
||
|
||
theorem getKey?_insertList [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : DistinctKeys toInsert) :
|
||
getKey? k (insertList l toInsert) = (getKey? k toInsert).or (getKey? k l) := by
|
||
simp only [getKey?_eq_getEntry?]
|
||
rw [getEntry?_insertList]
|
||
. simp only [Option.map_or]
|
||
. exact distinct_l
|
||
. exact DistinctKeys_impl_Pairwise_distinct distinct_toInsert
|
||
|
||
theorem getKey_insertList_of_contains_right [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : DistinctKeys toInsert)
|
||
{m} : (contains : containsKey k toInsert = true) →
|
||
getKey k (insertList l toInsert) m = getKey k toInsert contains := by
|
||
intro contains
|
||
unfold getKey
|
||
have get_is_some : (getKey? k (insertList l toInsert)).isSome = true := by
|
||
simp only [getKey?_eq_getEntry?, Option.isSome_map]
|
||
simp only [←@containsKey_eq_isSome_getEntry? α β _ (insertList l toInsert) k, m]
|
||
apply Option.get_congr
|
||
. rw [@getKey?_insertList α β _ _ l toInsert k distinct_l distinct_toInsert]
|
||
apply Option.or_of_isSome
|
||
. simp only [getKey?_eq_getEntry?, Option.isSome_map]
|
||
simp only [←@containsKey_eq_isSome_getEntry? α β _ toInsert k, contains]
|
||
|
||
theorem getKeyD_insertList_of_contains_right [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k fallback : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : DistinctKeys toInsert) :
|
||
containsKey k toInsert →
|
||
getKeyD k (insertList l toInsert) fallback = getKeyD k toInsert fallback := by
|
||
intro contains
|
||
simp only [getKeyD_eq_getKey?]
|
||
rw [@getKey?_insertList _ _ _ _ l toInsert k distinct_l distinct_toInsert]
|
||
rw [@getKey?_eq_some_getKey _ _ _ toInsert k contains]
|
||
simp only [Option.some_or, Option.getD_some]
|
||
|
||
theorem getKey!_insertList_of_contains_right_eq_false [Inhabited α] [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k : α}
|
||
(not_contains: containsKey k toInsert = false) :
|
||
getKey! k (insertList l toInsert) = getKey! k l := by
|
||
simp only [getKey!_eq_getKey?]
|
||
congr 1
|
||
simp only [getKey?_eq_getEntry?]
|
||
congr 1
|
||
simp [getEntry?_insertList_of_contains_eq_false not_contains]
|
||
|
||
theorem getKey?_insertList_of_contains_eq_false_right [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k : α}
|
||
(not_contains : containsKey k toInsert = false) :
|
||
List.getKey? k (insertList l toInsert) =
|
||
List.getKey? k l := by
|
||
rw [getKey?_eq_getEntry?, getKey?_eq_getEntry?]
|
||
congr 1
|
||
apply getEntry?_insertList_of_contains_eq_false not_contains
|
||
|
||
theorem getKey?_insertList_of_contains_eq_false_left [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : DistinctKeys toInsert)
|
||
(not_contains : containsKey k l = false) :
|
||
List.getKey? k (insertList l toInsert) =
|
||
List.getKey? k toInsert := by
|
||
rw [getKey?_eq_getEntry?, getKey?_eq_getEntry?]
|
||
congr 1
|
||
apply getEntry?_insertList_of_contains_left_eq_false distinct_l (DistinctKeys_impl_Pairwise_distinct distinct_toInsert) not_contains
|
||
|
||
theorem getKey_insertList_of_contains_left_of_contains_right_eq_false [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k : α} {m}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : DistinctKeys toInsert) :
|
||
(mem : containsKey k l) →
|
||
(∃ (mem₂ : containsKey k toInsert), getKey k (insertList l toInsert) m = getKey k toInsert mem₂)
|
||
∨ getKey k (insertList l toInsert) m = getKey k l mem := by
|
||
intro mem
|
||
apply Or.elim <| Classical.em <| containsKey k toInsert = true
|
||
case left =>
|
||
intro toInsert_contains_k
|
||
apply Or.inl
|
||
refine ⟨toInsert_contains_k, ?_⟩
|
||
apply getKey_insertList_of_contains_right
|
||
. exact distinct_l
|
||
. exact distinct_toInsert
|
||
case right =>
|
||
intro toInsert_not_contains_k
|
||
apply Or.inr
|
||
suffices some (getKey k (insertList l toInsert) m) = some (getKey k l mem) from by
|
||
injection this
|
||
simp only [← getKey?_eq_some_getKey]
|
||
rw [@List.getKey?_insertList_of_contains_eq_false_right α β _ _ l toInsert k (by simp only [toInsert_not_contains_k])]
|
||
|
||
theorem getKeyD_insertList [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k fallback : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : DistinctKeys toInsert) :
|
||
getKeyD k (insertList l toInsert) fallback = getKeyD k toInsert (getKeyD k l fallback) := by
|
||
simp only [getKeyD_eq_getKey?]
|
||
rw [@getKey?_insertList α β _ _ l toInsert k distinct_l distinct_toInsert]
|
||
simp only [Option.getD_or]
|
||
|
||
theorem List.getKeyD_insertList_of_contains_eq_false_right [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k fallback : α}
|
||
(not_contains: containsKey k toInsert = false) :
|
||
List.getKeyD k (insertList l toInsert) fallback = List.getKeyD k l fallback := by
|
||
simp only [getKeyD_eq_getKey?]
|
||
congr 1
|
||
simp only [getKey?_eq_getEntry?]
|
||
congr 1
|
||
apply getEntry?_insertList_of_contains_eq_false
|
||
. exact not_contains
|
||
|
||
theorem List.getKeyD_insertList_of_contains_eq_false_left [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k fallback : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : DistinctKeys toInsert)
|
||
(not_contains: containsKey k l = false) :
|
||
List.getKeyD k (insertList l toInsert) fallback = List.getKeyD k toInsert fallback := by
|
||
simp only [getKeyD_eq_getKey?]
|
||
congr 1
|
||
simp only [getKey?_eq_getEntry?]
|
||
congr 1
|
||
apply getEntry?_insertList_of_contains_left_eq_false
|
||
. exact distinct_l
|
||
. exact DistinctKeys_impl_Pairwise_distinct distinct_toInsert
|
||
. exact not_contains
|
||
|
||
theorem getKey!_insertList_of_contains_left_eq_false [BEq α] [EquivBEq α] [Inhabited α]
|
||
{l toInsert : List ((a : α) × β a)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : DistinctKeys toInsert) :
|
||
(containsKey k l = false) →
|
||
getKey! k (insertList l toInsert) = getKey! k toInsert := by
|
||
have distinct_toInsert_equiv : List.Pairwise (fun a b => (a.fst == b.fst) = false) toInsert := by
|
||
cases distinct_toInsert
|
||
case mk distinct_toInsert =>
|
||
simp only [keys_eq_map] at distinct_toInsert
|
||
apply List.Pairwise.of_map
|
||
case p => exact distinct_toInsert
|
||
simp only [imp_self, implies_true]
|
||
intro not_contains
|
||
simp only [getKey!_eq_getKey?]
|
||
congr 1
|
||
simp only [getKey?_eq_getEntry?]
|
||
congr 1
|
||
apply getEntry?_insertList_of_contains_left_eq_false
|
||
. exact distinct_l
|
||
. exact distinct_toInsert_equiv
|
||
. exact not_contains
|
||
|
||
theorem getValueCast?_insertList_of_contains_eq_false_left [BEq α] [LawfulBEq α] {l toInsert : List ((a : α) × β a)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert) : (containsKey k l = false) →
|
||
getValueCast? k (insertList l toInsert) = getValueCast? k toInsert := by
|
||
intro not_contains
|
||
rw [getValueCast?_eq_getEntry?, getValueCast?_eq_getEntry?]
|
||
have := @getEntry?_insertList_of_contains_left_eq_false α β _ _ l toInsert k distinct_l (DistinctKeys_impl_Pairwise_distinct distinct_toInsert) not_contains
|
||
simp only [this]
|
||
|
||
theorem getValueCast?_of_insertList [BEq α] [LawfulBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert) :
|
||
getValueCast? k (insertList l toInsert) = (getValueCast? k toInsert).or (getValueCast? k l) := by
|
||
apply Or.elim <| Classical.em <| (containsKey k toInsert)
|
||
case left =>
|
||
intro contains
|
||
rw [@getValueCast?_eq_some_getValueCast α β _ _ toInsert k contains]
|
||
rw [Option.some_or]
|
||
simp [← getValueCast?_eq_some_getValueCast]
|
||
simp [getValueCast?_eq_getEntry?]
|
||
apply Option.dmap_congr
|
||
. simp only [implies_true]
|
||
. rw [@getEntry?_insertList α β _ _ l toInsert distinct_l (DistinctKeys_impl_Pairwise_distinct distinct_toInsert) k]
|
||
rw [containsKey_eq_isSome_getEntry?] at contains
|
||
rw [Option.eq_some_of_isSome contains]
|
||
simp only [Option.some_or]
|
||
case right =>
|
||
intro not_contains
|
||
simp only [Bool.not_eq_true] at not_contains
|
||
rw [@List.getValueCast?_eq_none α β _ _ toInsert k not_contains, Option.none_or]
|
||
apply getValueCast?_insertList_of_contains_eq_false
|
||
. rw [← containsKey_eq_contains_map_fst]
|
||
exact not_contains
|
||
|
||
theorem getValueCastD_of_insertList [BEq α] [LawfulBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k : α} {fallback : β k}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert) :
|
||
getValueCastD k (insertList l toInsert) fallback = getValueCastD k toInsert (getValueCastD k l fallback) := by
|
||
rw [getValueCastD_eq_getValueCast?]
|
||
have getOr := @getValueCast?_of_insertList α β _ _ l toInsert k distinct_l distinct_toInsert
|
||
rw [getOr]
|
||
simp only [Option.getD_or, getValueCastD_eq_getValueCast?]
|
||
|
||
theorem List.getValueCast_insertList_of_contains_eq_false_left [BEq α] [LawfulBEq α] {l toInsert : List ((a : α) × β a)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert)
|
||
(contains : containsKey k (insertList l toInsert))
|
||
(not_contains: containsKey k l = false) :
|
||
getValueCast k (insertList l toInsert) contains = getValueCast k toInsert (contains_of_contains_insertList_of_contains_eq_false_left contains not_contains) := by
|
||
suffices h : some (getValueCast k (insertList l toInsert) contains) = some (getValueCast k toInsert (contains_of_contains_insertList_of_contains_eq_false_left contains not_contains)) from by
|
||
injection h
|
||
rw [← getValueCast?_eq_some_getValueCast, ← getValueCast?_eq_some_getValueCast]
|
||
exact getValueCast?_insertList_of_contains_eq_false_left distinct_l distinct_toInsert not_contains
|
||
|
||
theorem List.getKey_insertList_of_contains_eq_false_left [BEq α] [EquivBEq α] {l toInsert : List ((a : α) × β a)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert)
|
||
(contains : containsKey k (insertList l toInsert))
|
||
(not_contains: containsKey k l = false) :
|
||
getKey k (insertList l toInsert) contains = getKey k toInsert (contains_of_contains_insertList_of_contains_eq_false_left contains not_contains) := by
|
||
suffices h : some (getKey k (insertList l toInsert) contains) = some (getKey k toInsert (contains_of_contains_insertList_of_contains_eq_false_left contains not_contains)) from by
|
||
injection h
|
||
simp only [← getKey?_eq_some_getKey]
|
||
exact getKey?_insertList_of_contains_eq_false_left distinct_l distinct_toInsert not_contains
|
||
|
||
theorem List.getValueCast_insertList_of_contains_right [BEq α] [LawfulBEq α] {l toInsert : List ((a : α) × β a)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert)
|
||
(contains : containsKey k toInsert) {h} :
|
||
getValueCast k (insertList l toInsert) h = getValueCast k toInsert contains := by
|
||
suffices h : some (getValueCast k (insertList l toInsert) h) = some (getValueCast k toInsert contains) from by
|
||
injection h
|
||
simp only [← getValueCast?_eq_some_getValueCast]
|
||
simp only [getValueCast?_eq_getEntry?]
|
||
suffices getEntry? k (insertList l toInsert) = getEntry? k toInsert from by simp [this]
|
||
rw [@getEntry?_insertList α β _ _ l toInsert distinct_l (DistinctKeys_impl_Pairwise_distinct distinct_toInsert) k]
|
||
rw [containsKey_eq_isSome_getEntry?] at contains
|
||
rw [@Option.or_of_isSome _ (getEntry? k toInsert) (getEntry? k l) contains]
|
||
|
||
theorem List.getValueCastD_insertList_of_contains_eq_false_left [BEq α] [LawfulBEq α] {l toInsert : List ((a : α) × β a)} {k : α} {fallback : β k}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert)
|
||
(not_contains: containsKey k l = false) :
|
||
getValueCastD k (insertList l toInsert) fallback = getValueCastD k toInsert fallback := by
|
||
simp only [getValueCastD_eq_getValueCast?]
|
||
congr 1
|
||
exact getValueCast?_insertList_of_contains_eq_false_left distinct_l distinct_toInsert not_contains
|
||
|
||
theorem length_insertList_distinct [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : DistinctKeys toInsert) :
|
||
(∀ (a : α), containsKey a l → containsKey a toInsert = false) →
|
||
(insertList l toInsert).length = l.length + toInsert.length := by
|
||
replace distinct_toInsert := DistinctKeys_impl_Pairwise_distinct distinct_toInsert
|
||
intro distinct_keys
|
||
have subgoal2 : ∀ (a : α), containsKey a l = true → (List.map Sigma.fst toInsert).contains a = false := by
|
||
intro a h_contains
|
||
specialize distinct_keys a h_contains
|
||
rwa [containsKey_eq_contains_map_fst] at distinct_keys
|
||
apply length_insertList distinct_l distinct_toInsert subgoal2
|
||
|
||
theorem getKey?_insertList_of_mem_of_not_mem [BEq α] [LawfulBEq α]
|
||
{l toInsert : List ((a : α) × β a)} {k : α}
|
||
(contains : containsKey k l)
|
||
(not_contains : containsKey k toInsert = false) :
|
||
List.getKey? k (insertList l toInsert) = some k := by
|
||
simp only [List.getKey?_insertList_of_contains_eq_false_right not_contains, getKey?_eq_some contains]
|
||
|
||
theorem _root_.Option.or_eq_left_of_isSome {o o' : Option α} : o.isSome = true → o.or o' = o := by
|
||
cases o <;> simp
|
||
|
||
theorem insertListIfNew_perm_insertList [BEq α] [EquivBEq α] {l₁ l₂ : List ((a : α) × β a)}
|
||
(hd₁ : DistinctKeys l₁) (hd₂ : DistinctKeys l₂) :
|
||
List.Perm (insertListIfNew l₁ l₂) (insertList l₂ l₁) := by
|
||
induction l₂ using assoc_induction generalizing l₁ with
|
||
| nil =>
|
||
simp only [insertListIfNew]
|
||
exact Perm.trans (by simp) (perm_insertList hd₂ (pairwise_fst_eq_false hd₁) (by simp)).symm
|
||
| cons k v l ih =>
|
||
simp only [insertListIfNew]
|
||
refine Perm.trans (ih hd₁.insertEntryIfNew hd₂.tail) ?_
|
||
refine getEntry?_ext hd₂.tail.insertList hd₂.insertList (fun k' => ?_)
|
||
rw [getEntry?_insertList hd₂.tail (pairwise_fst_eq_false hd₁.insertEntryIfNew),
|
||
getEntry?_insertList hd₂ (pairwise_fst_eq_false hd₁), getEntry?_insertEntryIfNew]
|
||
simp only [Bool.and_eq_true, Bool.not_eq_eq_eq_not, Bool.not_true]
|
||
split
|
||
· rename_i h
|
||
rw [Option.some_or, Option.or_eq_right_of_none, getEntry?_cons_of_true h.1]
|
||
rw [← getEntry?_congr h.1, getEntry?_eq_none, h.2]
|
||
· rename_i h
|
||
rw [getEntry?_cons]
|
||
by_cases hk : k == k'
|
||
· simp only [hk, true_and, Bool.not_eq_false] at h
|
||
suffices (getEntry? k' l₁).isSome by simp [Option.or_eq_left_of_isSome this]
|
||
rwa [← containsKey_eq_isSome_getEntry?, ← containsKey_congr hk]
|
||
· simp [hk]
|
||
|
||
theorem insertList_perm_insertSmallerList [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : DistinctKeys toInsert) :
|
||
(insertList l toInsert).Perm
|
||
(insertSmallerList l toInsert) := by
|
||
unfold insertSmallerList
|
||
split
|
||
. apply Perm.symm
|
||
. apply insertListIfNew_perm_insertList distinct_toInsert distinct_l
|
||
. apply Perm.refl
|
||
|
||
theorem length_left_le_length_insertListIfNew [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} :
|
||
l.length ≤ (insertListIfNew 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_right_le_length_insertList [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : DistinctKeys toInsert) :
|
||
toInsert.length ≤ (List.insertList l toInsert).length := by
|
||
apply Nat.le_trans
|
||
case m => exact (insertListIfNew toInsert l).length
|
||
. apply length_left_le_length_insertListIfNew
|
||
. apply Nat.le_of_eq
|
||
. apply Perm.length_eq
|
||
. exact @insertListIfNew_perm_insertList α β _ _ toInsert l distinct_toInsert distinct_l
|
||
|
||
theorem insertList_insertEntry_right_equiv_insertEntry_insertList [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((a : α) × β a)} (p : (a : α) × β a)
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert : DistinctKeys toInsert) :
|
||
(insertList l (insertEntry p.fst p.snd toInsert)).Perm
|
||
(insertEntry p.fst p.snd (insertList l toInsert)) := by
|
||
apply getEntry?_ext (DistinctKeys.insertList distinct_l)
|
||
<| DistinctKeys.insertEntry
|
||
<| DistinctKeys.insertList distinct_l
|
||
intro a
|
||
have distinct_toInsert_pairwise := DistinctKeys_impl_Pairwise_distinct <| @DistinctKeys.insertEntry α β _ _ toInsert p.fst p.snd distinct_toInsert
|
||
simp only [@getEntry?_insertList α β _ _ l (insertEntry p.fst p.snd toInsert) distinct_l distinct_toInsert_pairwise a,
|
||
getEntry?_insertEntry]
|
||
split
|
||
. simp only [Option.some_or]
|
||
. rw [@getEntry?_insertList α β _ _ l toInsert distinct_l (DistinctKeys_impl_Pairwise_distinct distinct_toInsert) a]
|
||
|
||
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 using h₂
|
||
|
||
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 using not_contains
|
||
|
||
theorem getKey?_insertListConst_of_mem [BEq α] [EquivBEq α]
|
||
{l : List ((_ : α) × β)} {toInsert : List (α × β)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' : α} (k_beq : k == k')
|
||
(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 distinct_l k_beq
|
||
· 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 (α × β)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' : α} (k_beq : k == k')
|
||
(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 distinct_l k_beq 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 (α × β)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' : α} (k_beq : k == k')
|
||
(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 distinct_l k_beq 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 (α × β)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' fallback : α} (k_beq : k == k')
|
||
(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 distinct_l k_beq 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 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 using not_contains
|
||
|
||
theorem List.getValue?_insertList_of_contains_eq_false_right [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((_ : α) × β)} {k : α}
|
||
(not_contains : containsKey k toInsert = false) :
|
||
getValue? k (insertList l toInsert) = getValue? k l := by
|
||
rw [getValue?_eq_getEntry?, getValue?_eq_getEntry?]
|
||
simp only [getEntry?_insertList_of_contains_eq_false not_contains]
|
||
|
||
theorem List.getValueD_insertList_of_contains_eq_false_right [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((_ : α) × β)} {k : α} {fallback : β}
|
||
(not_contains : containsKey k toInsert = false) :
|
||
getValueD k (insertList l toInsert) fallback = getValueD k l fallback := by
|
||
simp only [getValueD_eq_getValue?]
|
||
congr 1
|
||
exact getValue?_insertList_of_contains_eq_false_right not_contains
|
||
|
||
theorem List.getValue_insertList_of_contains_eq_false_right [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((_ : α) × β)} {k : α}
|
||
(not_contains : containsKey k toInsert = false)
|
||
{p1 : containsKey k (insertList l toInsert) = true}
|
||
{p2 : containsKey k l = true} :
|
||
getValue k (insertList l toInsert) p1 = getValue k l p2 := by
|
||
suffices some (getValue k (insertList l toInsert) p1) = some (getValue k l p2) from by
|
||
injection this
|
||
simp only [← getValue?_eq_some_getValue]
|
||
apply List.getValue?_insertList_of_contains_eq_false_right not_contains
|
||
|
||
theorem List.getValue?_insertList_of_contains_eq_false_left [BEq α] [EquivBEq α] {l toInsert : List ((_ : α) × β)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert) : (containsKey k l = false) →
|
||
getValue? k (insertList l toInsert) = getValue? k toInsert := by
|
||
intro not_contains
|
||
simp only [getValue?_eq_getEntry?]
|
||
congr 1
|
||
exact getEntry?_insertList_of_contains_left_eq_false distinct_l (DistinctKeys_impl_Pairwise_distinct distinct_toInsert) not_contains
|
||
|
||
theorem List.getValueD_insertList_of_contains_eq_false_left [BEq α] [EquivBEq α] {l toInsert : List ((_ : α) × β)} {k : α} {fallback : β}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert) : (containsKey k l = false) →
|
||
getValueD k (insertList l toInsert) fallback = getValueD k toInsert fallback := by
|
||
intro not_contains
|
||
simp only [getValueD_eq_getValue?]
|
||
congr 1
|
||
exact getValue?_insertList_of_contains_eq_false_left distinct_l distinct_toInsert not_contains
|
||
|
||
theorem List.getValue?_insertList [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((_ : α) × β)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert) :
|
||
getValue? k (insertList l toInsert) = (getValue? k toInsert).or (getValue? k l) := by
|
||
simp only [getValue?_eq_getEntry?]
|
||
simp only [← Option.map_or]
|
||
congr 1
|
||
apply getEntry?_insertList distinct_l (DistinctKeys_impl_Pairwise_distinct distinct_toInsert)
|
||
|
||
theorem getValueD_insertList [BEq α] [EquivBEq α]
|
||
{l toInsert : List ((_ : α) × β)} {k : α} {fallback : β}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert) :
|
||
getValueD k (insertList l toInsert) fallback = getValueD k toInsert (getValueD k l fallback) := by
|
||
simp only [getValueD_eq_getValue?]
|
||
simp only [← Option.getD_or]
|
||
congr 1
|
||
apply List.getValue?_insertList distinct_l distinct_toInsert
|
||
|
||
theorem List.getValue_insertList_of_contains_eq_false_left [BEq α] [EquivBEq α] {l toInsert : List ((_ : α) × β)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert)
|
||
(contains : containsKey k (insertList l toInsert))
|
||
(not_contains: containsKey k l = false) :
|
||
getValue k (insertList l toInsert) contains = getValue k toInsert (contains_of_contains_insertList_of_contains_eq_false_left contains not_contains) := by
|
||
suffices some (getValue k (insertList l toInsert) contains) = some (getValue k toInsert (contains_of_contains_insertList_of_contains_eq_false_left contains not_contains)) from by
|
||
injection this
|
||
simp only [← getValue?_eq_some_getValue]
|
||
simp only [ getValue?_eq_getEntry? ]
|
||
congr 1
|
||
exact getEntry?_insertList_of_contains_left_eq_false distinct_l (DistinctKeys_impl_Pairwise_distinct distinct_toInsert) not_contains
|
||
|
||
theorem List.getValue_insertList_of_contains_right [BEq α] [EquivBEq α] {l toInsert : List ((_ : α) × β)} {k : α}
|
||
(distinct_l : DistinctKeys l)
|
||
(distinct_toInsert: DistinctKeys toInsert)
|
||
(contains : containsKey k toInsert) {h} :
|
||
getValue k (insertList l toInsert) h = getValue k toInsert contains := by
|
||
suffices some (getValue k (insertList l toInsert) h) = some (getValue k toInsert contains) from by
|
||
injection this
|
||
simp only [← getValue?_eq_some_getValue]
|
||
simp only [ getValue?_eq_getEntry? ]
|
||
congr 1
|
||
apply getEntry?_insertList_of_contains_eq_true
|
||
. exact distinct_l
|
||
. exact DistinctKeys_impl_Pairwise_distinct distinct_toInsert
|
||
. exact contains
|
||
|
||
theorem getValue?_insertListConst_of_mem [BEq α] [EquivBEq α]
|
||
{l : List ((_ : α) × β)} {toInsert : List (α × β)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' : α} (k_beq : k == k') {v : β}
|
||
(distinct_toInsert : toInsert.Pairwise (fun a b => (a.1 == b.1) = false))
|
||
(mem : ⟨k, v⟩ ∈ toInsert) :
|
||
getValue? k' (insertListConst l toInsert) = some 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 (α × β)}
|
||
(distinct_l : DistinctKeys l)
|
||
{k k' : α} (k_beq : k == k') {v : β}
|
||
(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 distinct_l k_beq 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: β}
|
||
(distinct_l : DistinctKeys l)
|
||
(k_beq : k == k')
|
||
(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 distinct_l k_beq 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: β}
|
||
(distinct_l : DistinctKeys l)
|
||
(k_beq : k == k')
|
||
(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 distinct_l k_beq 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_ite]
|
||
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]
|
||
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_iff, 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_iff,
|
||
Option.or_eq_some_iff, 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.rfl, Bool.true_or,
|
||
] 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,
|
||
] 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
|
||
|
||
private theorem Option.map_cast_apply {γ γ' : Type u} (h : γ = γ') (x : Option γ) :
|
||
Option.map (cast h) x = cast (congrArg Option h) x := by
|
||
cases h; cases x <;> simp
|
||
|
||
private theorem cast_eq_id {α : Type u} : cast (rfl : α = α) = id := by rfl
|
||
|
||
private theorem function_id_comp {α : Type u} {β : Type v} {f : α → β} :
|
||
id ∘ f = f := rfl
|
||
|
||
section Alter
|
||
|
||
section Dependent
|
||
|
||
variable [BEq α] [LawfulBEq α]
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def alterKey (k : α) (f : Option (β k) → Option (β k))
|
||
(l : List ((a : α) × β a)) : List ((a : α) × β a) :=
|
||
match f (getValueCast? k l) with
|
||
| none => eraseKey k l
|
||
| some v => insertEntry k v l
|
||
|
||
theorem length_alterKey {k : α} {f : Option (β k) → Option (β k)} {l : List ((a : α) × β a)} :
|
||
(alterKey k f l).length =
|
||
if h : containsKey k l then
|
||
if f (some <| getValueCast k l h) |>.isSome then l.length else l.length - 1
|
||
else
|
||
if f none |>.isSome then l.length + 1 else l.length := by
|
||
rw [alterKey]
|
||
cases h : getValueCast? k l <;> split <;> simp_all [length_eraseKey, length_insertEntry,
|
||
containsKey_eq_isSome_getValueCast?, ← getValueCast?_eq_some_getValueCast]
|
||
|
||
theorem length_alterKey' {k : α} {f : Option (β k) → Option (β k)} {l : List ((a : α) × β a)} :
|
||
(alterKey k f l).length =
|
||
if containsKey k l ∧ (f (getValueCast? k l)).isNone then
|
||
l.length - 1
|
||
else if containsKey k l = false ∧ (f (getValueCast? k l)).isSome then
|
||
l.length + 1
|
||
else
|
||
l.length := by
|
||
rw [alterKey]
|
||
cases h : containsKey k l <;> split <;> split <;> simp_all [length_eraseKey, length_insertEntry]
|
||
|
||
theorem alterKey_cons_perm {k : α} {f : Option (β k) → Option (β k)} {k' : α} {v' : β k'}
|
||
{l : List ((a : α) × β a)} : Perm (alterKey k f (⟨k', v'⟩ :: l))
|
||
(if hk : k' == k then
|
||
match f (some (cast (congrArg β (eq_of_beq hk)) v')) with
|
||
| none => l
|
||
| some v => ⟨k, v⟩ :: l
|
||
else
|
||
⟨k', v'⟩ :: alterKey k f l) := by
|
||
rw [alterKey]
|
||
by_cases hk' : k' == k
|
||
· simp only [hk', ↓reduceDIte]
|
||
rw [getValueCast?_cons_of_true hk', eraseKey_cons_of_beq hk']
|
||
simp only [insertEntry_cons_of_beq hk']
|
||
rfl
|
||
· simp only [hk', Bool.false_eq_true, ↓reduceDIte]
|
||
rw [Bool.not_eq_true] at hk'
|
||
rw [getValueCast?_cons_of_false hk', eraseKey_cons_of_false hk', alterKey]
|
||
split
|
||
· rfl
|
||
· exact insertEntry_cons_of_false hk'
|
||
|
||
theorem isEmpty_alterKey_eq_isEmpty_eraseKey {k : α} {f : Option (β k) → Option (β k)}
|
||
{l : List ((a : α) × β a)} :
|
||
(alterKey k f l).isEmpty = ((eraseKey k l).isEmpty && (f (getValueCast? k l)).isNone) := by
|
||
rw [alterKey, Bool.eq_iff_iff, Bool.and_eq_true_iff]
|
||
cases f (getValueCast? k l)
|
||
repeat simp [isEmpty_insertEntry]
|
||
|
||
theorem isEmpty_alterKey {k : α} {f : Option (β k) → Option (β k)} {l : List ((a : α) × β a)} :
|
||
(alterKey k f l).isEmpty = ((l.isEmpty || (l.length == 1 && containsKey k l)) &&
|
||
(f (getValueCast? k l)).isNone) := by
|
||
rw [isEmpty_alterKey_eq_isEmpty_eraseKey, isEmpty_eraseKey]
|
||
|
||
theorem alterKey_of_perm {a : α} {f : Option (β a) → Option (β a)} {l l' : List ((a : α) × β a)}
|
||
(hl : DistinctKeys l) (hp : Perm l l') : Perm (alterKey a f l) (alterKey a f l') := by
|
||
simp only [alterKey, getValueCast?_of_perm hl hp]
|
||
split
|
||
· exact eraseKey_of_perm hl hp
|
||
· exact insertEntry_of_perm hl hp
|
||
|
||
theorem alterKey_append_of_containsKey_right_eq_false {a : α} {f : Option (β a) → Option (β a)}
|
||
{l l' : List ((a : α) × β a)} (hc : containsKey a l' = false) :
|
||
alterKey a f (l ++ l') = alterKey a f l ++ l' := by
|
||
simp only [alterKey, getValueCast?_append_of_containsKey_eq_false hc,
|
||
eraseKey_append_of_containsKey_right_eq_false hc, insertEntry_append_of_not_contains_right hc]
|
||
split <;> rfl
|
||
|
||
@[simp]
|
||
theorem alterKey_nil {a : α} {f : Option (β a) → Option (β a)} :
|
||
alterKey a f [] = match f none with
|
||
| none => []
|
||
| some b => [⟨a, b⟩] := (rfl)
|
||
|
||
theorem containsKey_alterKey_self {a : α} {f : Option (β a) → Option (β a)}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
containsKey a (alterKey a f l) = (f (getValueCast? a l)).isSome := by
|
||
match l with
|
||
| [] =>
|
||
simp only [getValueCast?_nil, alterKey_nil]
|
||
cases f none <;> simp
|
||
| x :: xs =>
|
||
simp only [alterKey]
|
||
cases f (getValueCast? a (x :: xs))
|
||
· simp only [hl, Option.isSome_none, containsKey_eraseKey_self]
|
||
· simp only [containsKey_insertEntry, BEq.rfl, Bool.true_or, Option.isSome_some]
|
||
|
||
theorem containsKey_alterKey {k k' : α} {f : Option (β k) → Option (β k)}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
containsKey k' (alterKey k f l) =
|
||
if k == k' then
|
||
f (getValueCast? k l) |>.isSome
|
||
else
|
||
containsKey k' l := by
|
||
split
|
||
next h =>
|
||
rw [← containsKey_congr h, containsKey_alterKey_self hl]
|
||
next h =>
|
||
rw [alterKey]
|
||
cases f (getValueCast? k l)
|
||
· simp [containsKey_eraseKey_of_false (Bool.not_eq_true _ ▸ h)]
|
||
· simp_all
|
||
|
||
theorem DistinctKeys.alterKey {a : α} {f : Option (β a) → Option (β a)}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) : DistinctKeys (alterKey a f l) := by
|
||
dsimp only [List.alterKey]
|
||
split
|
||
· exact DistinctKeys.eraseKey hl
|
||
· exact DistinctKeys.insertEntry hl
|
||
|
||
theorem mem_alterKey_of_key_ne {a : α} {f : Option (β a) → Option (β a)}
|
||
{l : List ((a : α) × β a)} (p : (a : α) × β a) (hne : p.1 ≠ a) :
|
||
p ∈ alterKey a f l ↔ p ∈ l := by
|
||
rw [alterKey]
|
||
split <;> simp only [mem_eraseKey_of_key_ne p hne, mem_insertEntry_of_key_ne p hne]
|
||
|
||
theorem getValueCast?_alterKey (k k' : α) (f : Option (β k) → Option (β k))
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) : getValueCast? k' (alterKey k f l) =
|
||
if h : k == k' then
|
||
cast (congrArg (Option ∘ β) (eq_of_beq h)) (f (getValueCast? k l))
|
||
else
|
||
getValueCast? k' l := by
|
||
split
|
||
next heq =>
|
||
cases eq_of_beq heq
|
||
simp only [Function.comp_apply, cast_eq]
|
||
rw [alterKey]
|
||
split
|
||
next hnone =>
|
||
simp only [getValueCast?_eraseKey_self hl, hnone]
|
||
next hsome =>
|
||
rw [hsome, getValueCast?_insertEntry_self]
|
||
next heq =>
|
||
rw [alterKey]
|
||
split
|
||
next hnone =>
|
||
simp only [heq, hl, getValueCast?_eraseKey, ite_false, Bool.false_eq_true,
|
||
]
|
||
next hsome =>
|
||
simp only [getValueCast?_insertEntry, dite_false, heq, Bool.false_eq_true]
|
||
|
||
theorem getValueCast_alterKey (k k' : α) (f : Option (β k) → Option (β k))
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) (hc : containsKey k' (alterKey k f l)) :
|
||
getValueCast k' (alterKey k f l) hc =
|
||
if h : k == k' then
|
||
haveI hc' : (f (getValueCast? k l)).isSome := by
|
||
rwa [containsKey_alterKey hl, if_pos h] at hc
|
||
cast (congrArg β (eq_of_beq h)) <| (f (getValueCast? k l)).get hc'
|
||
else
|
||
haveI hc' : containsKey k' l := by rwa [containsKey_alterKey hl, if_neg h] at hc
|
||
getValueCast k' l hc' := by
|
||
have := getValueCast?_alterKey k k' f l hl
|
||
rw [getValueCast?_eq_some_getValueCast hc] at this
|
||
split
|
||
next heq =>
|
||
cases eq_of_beq heq
|
||
apply Option.some_inj.mp
|
||
simp_all
|
||
next heq =>
|
||
apply Option.some_inj.mp
|
||
simp_all only [Bool.false_eq_true, Function.comp_apply, dite_false]
|
||
rw [getValueCast?_eq_some_getValueCast]
|
||
|
||
theorem getValueCast_alterKey_self (k : α) (f : Option (β k) → Option (β k))
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) (hc : containsKey k (alterKey k f l)) :
|
||
haveI hc' : (f (getValueCast? k l)).isSome := by
|
||
rwa [containsKey_alterKey hl, beq_self_eq_true] at hc
|
||
getValueCast k (alterKey k f l) hc = (f (getValueCast? k l)).get hc' := by
|
||
rw [getValueCast_alterKey _ _ _ _ hl]
|
||
simp
|
||
|
||
theorem getValueCast!_alterKey {k k' : α} [Inhabited (β k')] {f : Option (β k) → Option (β k)}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) : getValueCast! k' (alterKey k f l) =
|
||
if heq : k == k' then
|
||
(f (getValueCast? k l)).map (cast (congrArg β <| eq_of_beq heq)) |>.get!
|
||
else
|
||
getValueCast! k' l := by
|
||
simp only [hl, getValueCast!_eq_getValueCast?, getValueCast?_alterKey, beq_iff_eq,
|
||
Function.comp_apply]
|
||
split
|
||
next heq =>
|
||
simp only [Option.map_cast_apply]
|
||
· rfl
|
||
|
||
theorem getValueCastD_alterKey {k k' : α} {fallback : β k'} {f : Option (β k) → Option (β k)}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) : getValueCastD k' (alterKey k f l) fallback =
|
||
if heq : k == k' then
|
||
f (getValueCast? k l) |>.map (cast (congrArg β <| eq_of_beq heq)) |>.getD fallback
|
||
else
|
||
getValueCastD k' l fallback := by
|
||
simp only [getValueCastD_eq_getValueCast?, hl, getValueCast?_alterKey, beq_iff_eq,
|
||
Function.comp_apply, apply_dite (Option.getD · fallback), Option.map_cast_apply]
|
||
|
||
theorem getKey?_alterKey {k k' : α} {f : Option (β k) → Option (β k)} (l : List ((a : α) × β a))
|
||
(hl : DistinctKeys l) :
|
||
getKey? k' (alterKey k f l) =
|
||
if k == k' then
|
||
if (f (getValueCast? k l)).isSome then some k else none
|
||
else
|
||
getKey? k' l := by
|
||
rw [alterKey]
|
||
split <;> next heq => simp [hl, heq, getKey?_eraseKey, getKey?_insertEntry]
|
||
|
||
theorem getKey!_alterKey [Inhabited α] {k k' : α} {f : Option (β k) → Option (β k)}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getKey! k' (alterKey k f l) =
|
||
if k == k' then
|
||
if (f (getValueCast? k l)).isSome then k else default
|
||
else
|
||
getKey! k' l := by
|
||
simp only [getKey!_eq_getKey?, hl, getKey?_alterKey, beq_iff_eq]
|
||
split
|
||
next heq =>
|
||
split <;> rfl
|
||
next heq =>
|
||
rfl
|
||
|
||
theorem getKey_alterKey {k k' : α} {f : Option (β k) → Option (β k)}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) (hc : containsKey k' (alterKey k f l)) :
|
||
getKey k' (alterKey k f l) hc =
|
||
if heq : k == k' then
|
||
k
|
||
else
|
||
haveI h' : containsKey k' l := by rwa [containsKey_alterKey hl, if_neg heq] at hc
|
||
getKey k' l h' := by
|
||
have := getKey?_alterKey (f := f) (k' := k') _ hl
|
||
rw [getKey?_eq_some_getKey hc] at this
|
||
split
|
||
next heq =>
|
||
cases eq_of_beq heq
|
||
apply Option.some_inj.mp
|
||
simp_all
|
||
next heq =>
|
||
apply Option.some_inj.mp
|
||
simp_all only [Bool.false_eq_true, ite_false]
|
||
rw [getKey?_eq_some_getKey]
|
||
|
||
theorem getKeyD_alterKey {k k' fallback : α} {f : Option (β k) → Option (β k)}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getKeyD k' (alterKey k f l) fallback =
|
||
if k == k' then
|
||
if (f (getValueCast? k l)).isSome then k else fallback
|
||
else
|
||
getKeyD k' l fallback := by
|
||
simp only [hl, getKeyD_eq_getKey?, getKey?_alterKey, beq_iff_eq]
|
||
split
|
||
next heq =>
|
||
split <;> rfl
|
||
· rfl
|
||
|
||
end Dependent
|
||
|
||
namespace Const
|
||
|
||
variable [BEq α]
|
||
|
||
variable {β : Type v}
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def alterKey [BEq α] (k : α) (f : Option β → Option β)
|
||
(l : List ((_ : α) × β)) : List ((_ : α) × β) :=
|
||
match f (getValue? k l) with
|
||
| none => eraseKey k l
|
||
| some v => insertEntry k v l
|
||
|
||
theorem length_alterKey {k : α} {f : Option β → Option β} {l : List ((_ : α) × β)} :
|
||
(alterKey k f l).length =
|
||
if h : containsKey k l then
|
||
if f (some (getValue k l h)) |>.isSome then l.length else l.length - 1
|
||
else
|
||
if f none |>.isSome then l.length + 1 else l.length := by
|
||
rw [alterKey]
|
||
cases h : getValue? k l <;> split <;> simp_all [length_eraseKey, length_insertEntry,
|
||
containsKey_eq_isSome_getValue?, ← getValue?_eq_some_getValue, -getValue?_eq_none]
|
||
|
||
theorem length_alterKey' {k : α} {f : Option β → Option β} {l : List ((_ : α) × β)} :
|
||
(alterKey k f l).length =
|
||
if containsKey k l ∧ (f (getValue? k l)).isNone then
|
||
l.length - 1
|
||
else if containsKey k l = false ∧ (f (getValue? k l)).isSome then
|
||
l.length + 1
|
||
else
|
||
l.length := by
|
||
rw [alterKey]
|
||
cases h : containsKey k l <;> split <;> split <;> simp_all [length_eraseKey, length_insertEntry]
|
||
|
||
theorem length_alterKey_eq_add_one {k : α} {f : Option β → Option β} {l : List ((_ : α) × β)}
|
||
(h : containsKey k l = false) (h' : (f (getValue? k l)).isSome) :
|
||
(alterKey k f l).length = l.length + 1 := by
|
||
simp [length_alterKey', h, h']
|
||
|
||
theorem length_alterKey_eq_sub_one {k : α} {f : Option β → Option β} {l : List ((_ : α) × β)}
|
||
(h : containsKey k l) (h' : (f (getValue? k l)).isNone) :
|
||
(alterKey k f l).length = l.length - 1 := by
|
||
simp [length_alterKey', h, h']
|
||
|
||
theorem length_alterKey_eq_self {k : α} {f : Option β → Option β} {l : List ((_ : α) × β)}
|
||
(h : containsKey k l) (h' : (f (getValue? k l)).isSome) :
|
||
(alterKey k f l).length = l.length := by
|
||
simp [length_alterKey', h, Option.isSome_iff_ne_none.mp h']
|
||
|
||
theorem length_alterKey_eq_self' {k : α} {f : Option β → Option β} {l : List ((_ : α) × β)}
|
||
(h : containsKey k l = false) (h' : (f (getValue? k l)).isNone) :
|
||
(alterKey k f l).length = l.length := by
|
||
simp [length_alterKey', h, h']
|
||
|
||
theorem alterKey_cons_perm {k : α} {f : Option β → Option β} {k' : α} {v' : β}
|
||
{l : List ((_ : α) × β)} :
|
||
Perm (alterKey k f (⟨k', v'⟩ :: l))
|
||
(if k' == k then
|
||
match f (some v') with
|
||
| none => l
|
||
| some v => ⟨k, v⟩ :: l
|
||
else
|
||
⟨k', v'⟩ :: alterKey k f l) := by
|
||
rw [alterKey]
|
||
by_cases hk' : k' == k
|
||
· simp only [hk']
|
||
rw [getValue?_cons_of_true hk', eraseKey_cons_of_beq hk']
|
||
simp only [insertEntry_cons_of_beq hk']
|
||
rfl
|
||
· simp only [hk', Bool.false_eq_true]
|
||
rw [Bool.not_eq_true] at hk'
|
||
rw [getValue?_cons_of_false hk', eraseKey_cons_of_false hk', alterKey]
|
||
split
|
||
· rfl
|
||
· simp [insertEntry_cons_of_false hk']
|
||
|
||
theorem isEmpty_alterKey_eq_isEmpty_eraseKey {k : α} {f : Option β → Option β}
|
||
{l : List ((_ : α) × β)} :
|
||
(alterKey k f l).isEmpty = ((eraseKey k l).isEmpty && (f (getValue? k l)).isNone) := by
|
||
simp only [alterKey]
|
||
split <;> { next heq => simp [heq] }
|
||
|
||
theorem isEmpty_alterKey {k : α} {f : Option β → Option β} {l : List ((_ : α) × β)} :
|
||
(alterKey k f l).isEmpty = ((l.isEmpty || (l.length == 1 && containsKey k l)) &&
|
||
(f (getValue? k l)).isNone) := by
|
||
rw [isEmpty_alterKey_eq_isEmpty_eraseKey, isEmpty_eraseKey]
|
||
|
||
theorem alterKey_of_perm [EquivBEq α] {a : α} {f : Option β → Option β} {l l' : List ((_ : α) × β)}
|
||
(hl : DistinctKeys l) (hp : Perm l l') :
|
||
Perm (alterKey a f l) (alterKey a f l') := by
|
||
simp only [alterKey, getValue?_of_perm hl hp]
|
||
split
|
||
· exact eraseKey_of_perm hl hp
|
||
· exact insertEntry_of_perm hl hp
|
||
|
||
theorem alterKey_append_of_containsKey_right_eq_false {a : α} {f : Option β → Option β}
|
||
{l l' : List ((_ : α) × β)} (hc : containsKey a l' = false) :
|
||
alterKey a f (l ++ l') = alterKey a f l ++ l' := by
|
||
simp only [alterKey, getValue?_append_of_containsKey_eq_false hc,
|
||
eraseKey_append_of_containsKey_right_eq_false hc, insertEntry_append_of_not_contains_right hc]
|
||
split <;> rfl
|
||
|
||
@[simp]
|
||
theorem alterKey_nil {a : α} {f : Option β → Option β} :
|
||
alterKey a f [] = match f none with
|
||
| none => []
|
||
| some b => [⟨a, b⟩] := (rfl)
|
||
|
||
theorem containsKey_alterKey_self [EquivBEq α] {a : α} {f : Option β → Option β}
|
||
{l : List ((_ : α) × β)} (hl : DistinctKeys l) :
|
||
containsKey a (alterKey a f l) = (f (getValue? a l)).isSome := by
|
||
match l with
|
||
| [] =>
|
||
simp only [getValue?_nil, alterKey_nil]
|
||
split <;> { rename_i heq; simp [heq] }
|
||
| x :: xs =>
|
||
simp only [alterKey]
|
||
split
|
||
next heq =>
|
||
simp only [hl, heq, Option.isSome_none, containsKey_eraseKey_self]
|
||
next heq =>
|
||
simp only [containsKey_insertEntry, BEq.rfl, Bool.true_or, heq, Option.isSome_some]
|
||
|
||
theorem mem_alterKey_of_key_not_beq [EquivBEq α] {β : Type v} {a : α} {f : Option β → Option β}
|
||
{l : List ((_ : α) × β)} (p : (_ : α) × β) (hne : (p.1 == a) = false) :
|
||
p ∈ alterKey a f l ↔ p ∈ l := by
|
||
rw [alterKey]
|
||
split <;> simp only
|
||
[mem_eraseKey_of_key_beq_eq_false p hne, mem_insertEntry_of_key_beq_eq_false p hne]
|
||
|
||
theorem containsKey_alterKey [EquivBEq α] {k k' : α} {f : Option β → Option β}
|
||
{l : List ((_ : α) × β)} (hl : DistinctKeys l) :
|
||
containsKey k' (alterKey k f l) =
|
||
if k == k' then
|
||
f (getValue? k l) |>.isSome
|
||
else
|
||
containsKey k' l := by
|
||
split
|
||
next h =>
|
||
rw [← containsKey_congr h]
|
||
exact containsKey_alterKey_self hl
|
||
next h =>
|
||
rw [alterKey]
|
||
split
|
||
next heq =>
|
||
simp only [containsKey_eraseKey_of_false (Bool.not_eq_true _ ▸ h)]
|
||
next heq =>
|
||
simp_all only [Bool.not_eq_true, containsKey_insertEntry, Bool.false_or]
|
||
|
||
theorem getValue?_alterKey [EquivBEq α] (k k' : α) (f : Option β → Option β)
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) : getValue? k' (alterKey k f l) =
|
||
if k == k' then
|
||
f (getValue? k l)
|
||
else
|
||
getValue? k' l := by
|
||
split
|
||
next heq =>
|
||
rw [alterKey]
|
||
split
|
||
next hnone =>
|
||
simp only [getValue?_eraseKey_of_beq hl heq, hnone]
|
||
next hsome =>
|
||
rw [hsome, getValue?_insertEntry_of_beq heq]
|
||
next heq =>
|
||
rw [alterKey]
|
||
split
|
||
next hnone =>
|
||
simp only [heq, hl, getValue?_eraseKey, ite_false, Bool.false_eq_true,
|
||
]
|
||
next hsome =>
|
||
simp only [getValue?_insertEntry, heq, Bool.false_eq_true, reduceIte]
|
||
|
||
theorem getValue_alterKey [EquivBEq α] (k k' : α) (f : Option β → Option β) (l : List ((_ : α) × β))
|
||
(hl : DistinctKeys l) (hc : containsKey k' (alterKey k f l)) :
|
||
getValue k' (alterKey k f l) hc =
|
||
if h : k == k' then
|
||
haveI hc' : (f (getValue? k l)).isSome := by rwa [containsKey_alterKey hl, if_pos h] at hc
|
||
(f (getValue? k l)).get hc'
|
||
else
|
||
haveI hc' : containsKey k' l := by rwa [containsKey_alterKey hl, if_neg h] at hc
|
||
getValue k' l hc' := by
|
||
have := getValue?_alterKey k k' f l hl
|
||
rw [getValue?_eq_some_getValue hc] at this
|
||
split
|
||
next heq =>
|
||
apply Option.some_inj.mp
|
||
simp_all
|
||
next heq =>
|
||
apply Option.some_inj.mp
|
||
simp_all only [Bool.false_eq_true, ite_false]
|
||
rw [getValue?_eq_some_getValue]
|
||
|
||
theorem getValue_alterKey_self [EquivBEq α] (k : α) (f : Option β → Option β)
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) (hc : containsKey k (alterKey k f l)) :
|
||
haveI hc' : (f (getValue? k l)).isSome := by rwa [containsKey_alterKey hl, BEq.rfl] at hc
|
||
getValue k (alterKey k f l) hc = (f (getValue? k l)).get hc' := by
|
||
rw [getValue_alterKey _ _ _ _ hl]
|
||
simp
|
||
|
||
theorem getValue!_alterKey [EquivBEq α] {k k' : α} [Inhabited β] {f : Option β → Option β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) :
|
||
getValue! k' (alterKey k f l) =
|
||
if k == k' then
|
||
(f (getValue? k l)).get!
|
||
else
|
||
getValue! k' l := by
|
||
simp only [hl, getValue!_eq_getValue?, getValue?_alterKey,
|
||
apply_ite Option.get!]
|
||
|
||
theorem getValueD_alterKey [EquivBEq α] {k k' : α} {fallback : β} {f : Option β → Option β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) :
|
||
getValueD k' (alterKey k f l) fallback =
|
||
if k == k' then
|
||
f (getValue? k l) |>.getD fallback
|
||
else
|
||
getValueD k' l fallback := by
|
||
simp only [hl, getValueD_eq_getValue?, getValue?_alterKey,
|
||
apply_ite (Option.getD · fallback)]
|
||
|
||
theorem getKey?_alterKey [EquivBEq α] {k k' : α} {f : Option β → Option β} (l : List ((_ : α) × β))
|
||
(hl : DistinctKeys l) :
|
||
getKey? k' (alterKey k f l) =
|
||
if k == k' then
|
||
if (f (getValue? k l)).isSome then some k else none
|
||
else
|
||
getKey? k' l := by
|
||
rw [alterKey]
|
||
split <;> next heq => simp [hl, heq, getKey?_eraseKey, getKey?_insertEntry]
|
||
|
||
theorem getKey!_alterKey [EquivBEq α] [Inhabited α] {k k' : α} {f : Option β → Option β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) :
|
||
getKey! k' (alterKey k f l) =
|
||
if k == k' then
|
||
if (f (getValue? k l)).isSome then k else default
|
||
else
|
||
getKey! k' l := by
|
||
simp [hl, getKey!_eq_getKey?, getKey?_alterKey, apply_ite Option.get!]
|
||
|
||
theorem getKey_alterKey [EquivBEq α] {k k' : α} {f : Option β → Option β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) (hc : containsKey k' (alterKey k f l)) :
|
||
getKey k' (alterKey k f l) hc =
|
||
if heq : k == k' then
|
||
k
|
||
else
|
||
haveI h' : containsKey k' l := by rwa [containsKey_alterKey hl, if_neg heq] at hc
|
||
getKey k' l h' := by
|
||
have := getKey?_alterKey (f := f) (k := k) (k' := k') _ hl
|
||
rw [getKey?_eq_some_getKey hc] at this
|
||
split
|
||
next heq =>
|
||
apply Option.some_inj.mp
|
||
simp_all
|
||
next heq =>
|
||
apply Option.some_inj.mp
|
||
simp_all only [Bool.false_eq_true, ite_false]
|
||
rw [getKey?_eq_some_getKey]
|
||
|
||
theorem getKeyD_alterKey [EquivBEq α] {k k' fallback : α} {f : Option β → Option β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) :
|
||
getKeyD k' (alterKey k f l) fallback =
|
||
if k == k' then
|
||
if (f (getValue? k l)).isSome then k else fallback
|
||
else
|
||
getKeyD k' l fallback := by
|
||
simp only [hl, getKeyD_eq_getKey?, getKey?_alterKey]
|
||
split
|
||
next heq =>
|
||
split <;> rfl
|
||
· rfl
|
||
|
||
end Const
|
||
|
||
theorem constAlterKey_eq_alterKey [BEq α] [LawfulBEq α] {β : Type v} {k : α}
|
||
{f : Option β → Option β} {l : List ((_ : α) × β)} : Const.alterKey k f l = alterKey k f l := by
|
||
rw [alterKey, Const.alterKey, getValue?_eq_getValueCast?]
|
||
cases f (getValueCast? k l) <;> rfl
|
||
|
||
theorem DistinctKeys.constAlterKey [BEq α] [EquivBEq α] {β : Type v} {a : α}
|
||
{f : Option β → Option β} {l : List ((_ : α) × β)} (hl : DistinctKeys l) :
|
||
DistinctKeys (List.Const.alterKey a f l) := by
|
||
dsimp only [List.Const.alterKey]
|
||
split
|
||
· exact DistinctKeys.eraseKey hl
|
||
· exact DistinctKeys.insertEntry hl
|
||
|
||
end Alter
|
||
|
||
section Modify
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def modifyKey [BEq α] [LawfulBEq α] (k : α) (f : β k → β k)
|
||
(l : List ((a : α) × β a)) : List ((a : α) × β a) :=
|
||
match getValueCast? k l with
|
||
| none => l
|
||
| some v => replaceEntry k (f v) l
|
||
|
||
theorem isEmpty_modifyKey [BEq α] [LawfulBEq α] (k : α) (f : β k → β k) (l : List ((a : α) × β a)) :
|
||
(modifyKey k f l).isEmpty = l.isEmpty := by
|
||
match l with
|
||
| [] => simp [modifyKey]
|
||
| a :: as =>
|
||
simp only [modifyKey, replaceEntry, cond_eq_ite]
|
||
repeat' split <;> simp
|
||
|
||
theorem length_modifyKey [BEq α] [LawfulBEq α] (k : α) (f : β k → β k) (l : List ((a : α) × β a)) :
|
||
(modifyKey k f l).length = l.length := by
|
||
induction l
|
||
· rfl
|
||
next ih =>
|
||
simp only [modifyKey]
|
||
split <;> next h => simp only [length_replaceEntry, List.length_cons]
|
||
|
||
theorem containsKey_modifyKey [BEq α] [LawfulBEq α] (k k' : α) (f : β k → β k)
|
||
(l : List ((a : α) × β a)) : containsKey k' (modifyKey k f l) = containsKey k' l := by
|
||
induction l
|
||
· simp only [modifyKey, getValueCast?_nil, containsKey_nil]
|
||
· simp only [modifyKey]
|
||
split
|
||
· rfl
|
||
· rw [containsKey_replaceEntry]
|
||
|
||
theorem modifyKey_eq_alterKey [BEq α] [LawfulBEq α] (k : α) (f : β k → β k)
|
||
(l : List ((a : α) × β a)) : modifyKey k f l = alterKey k (·.map f) l := by
|
||
rw [modifyKey, alterKey, Option.map.eq_def]
|
||
split <;> next h =>
|
||
simp [h, insertEntry, containsKey_eq_isSome_getValueCast?, eraseKey_of_containsKey_eq_false]
|
||
|
||
theorem DistinctKeys.modifyKey [BEq α] [LawfulBEq α] {a f} {l : List ((a : α) × β a)}
|
||
(hd : DistinctKeys l) : DistinctKeys (modifyKey a f l) := by
|
||
simpa [modifyKey_eq_alterKey] using hd.alterKey
|
||
|
||
theorem modifyKey_of_perm [BEq α] [LawfulBEq α] {l l' : List ((a : α) × β a)}
|
||
{k : α} {f : β k → β k} (hl : DistinctKeys l) (h : Perm l l') :
|
||
Perm (modifyKey k f l) (modifyKey k f l') := by
|
||
simp only [modifyKey_eq_alterKey, alterKey_of_perm hl h]
|
||
|
||
theorem getValueCast?_modifyKey [BEq α] [LawfulBEq α] {k k' : α} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getValueCast? k' (modifyKey k f l) =
|
||
if h : k == k' then
|
||
(cast (congrArg (Option ∘ β) (eq_of_beq h)) ((getValueCast? k l).map f))
|
||
else
|
||
getValueCast? k' l := by
|
||
simp [modifyKey_eq_alterKey, getValueCast?_alterKey, hl]
|
||
|
||
@[simp]
|
||
theorem getValueCast?_modifyKey_self [BEq α] [LawfulBEq α] {k : α} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getValueCast? k (modifyKey k f l) = (getValueCast? k l).map f := by
|
||
simp [getValueCast?_modifyKey, hl]
|
||
|
||
theorem getValueCast_modifyKey [BEq α] [LawfulBEq α] {k k' : α} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) (h : containsKey k' (modifyKey k f l)) :
|
||
getValueCast k' (modifyKey k f l) h =
|
||
if heq : k == k' then
|
||
haveI h' : containsKey k l := by rwa [containsKey_modifyKey, ← eq_of_beq heq] at h
|
||
cast (congrArg β (eq_of_beq heq)) <| f (getValueCast k l h')
|
||
else
|
||
haveI h' : containsKey k' l := by rwa [containsKey_modifyKey] at h
|
||
getValueCast k' l h' := by
|
||
simp only [modifyKey_eq_alterKey, getValueCast_alterKey, hl]
|
||
split
|
||
next heq =>
|
||
cases eq_of_beq heq
|
||
haveI h' : containsKey k l := by rwa [containsKey_modifyKey, ← eq_of_beq heq] at h
|
||
simp [getValueCast?_eq_some_getValueCast, h']
|
||
· rfl
|
||
|
||
@[simp]
|
||
theorem getValueCast_modifyKey_self [BEq α] [LawfulBEq α] {k : α} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) {h : containsKey k (modifyKey k f l)} :
|
||
haveI h' : containsKey k l := by rwa [containsKey_modifyKey] at h
|
||
getValueCast k (modifyKey k f l) h = f (getValueCast k l h') := by
|
||
simp [getValueCast_modifyKey, hl]
|
||
|
||
theorem getValueCast!_modifyKey [BEq α] [LawfulBEq α] {k k' : α} [hi : Inhabited (β k')]
|
||
{f : β k → β k} (l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getValueCast! k' (modifyKey k f l) =
|
||
if heq : k == k' then
|
||
getValueCast? k l |>.map f |>.map (cast (congrArg β (eq_of_beq heq))) |>.get!
|
||
else
|
||
getValueCast! k' l := by
|
||
simp only [modifyKey_eq_alterKey, getValueCast!_alterKey, hl]
|
||
|
||
@[simp]
|
||
theorem getValueCast!_modifyKey_self [BEq α] [LawfulBEq α] {k : α} [Inhabited (β k)]
|
||
{f : β k → β k} (l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getValueCast! k (modifyKey k f l) = ((getValueCast? k l).map f).get! := by
|
||
simp [getValueCast!_modifyKey, hl, List.cast_eq_id]
|
||
|
||
theorem getValueCastD_modifyKey [BEq α] [LawfulBEq α] {k k' : α} {fallback : β k'} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getValueCastD k' (modifyKey k f l) fallback =
|
||
if heq : k == k' then
|
||
getValueCast? k l |>.map f |>.map (cast (congrArg β <| eq_of_beq heq)) |>.getD fallback
|
||
else
|
||
getValueCastD k' l fallback := by
|
||
simp [modifyKey_eq_alterKey, getValueCastD_alterKey, hl]
|
||
|
||
@[simp]
|
||
theorem getValueCastD_modifyKey_self [BEq α] [LawfulBEq α] {k : α} {fallback : β k} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getValueCastD k (modifyKey k f l) fallback = ((getValueCast? k l).map f).getD fallback := by
|
||
simp [getValueCastD_modifyKey, hl, List.cast_eq_id]
|
||
|
||
theorem getKey?_modifyKey [BEq α] [LawfulBEq α] {k k' : α} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getKey? k' (modifyKey k f l) =
|
||
if k == k' then
|
||
if containsKey k l then some k else none
|
||
else
|
||
getKey? k' l := by
|
||
simp [modifyKey_eq_alterKey, getKey?_alterKey, containsKey_eq_isSome_getValueCast?, hl]
|
||
|
||
theorem getKey?_modifyKey_self [BEq α] [LawfulBEq α] {k : α} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getKey? k (modifyKey k f l) = if containsKey k l then some k else none := by
|
||
simp [getKey?_modifyKey, hl]
|
||
|
||
theorem getKey!_modifyKey [BEq α] [LawfulBEq α] [Inhabited α] {k k' : α} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getKey! k' (modifyKey k f l) =
|
||
if k == k' then
|
||
if containsKey k l then k else default
|
||
else
|
||
getKey! k' l := by
|
||
simp [modifyKey_eq_alterKey, getKey!_alterKey, containsKey_eq_isSome_getValueCast?, hl]
|
||
|
||
theorem getKey!_modifyKey_self [BEq α] [LawfulBEq α] [Inhabited α] {k : α} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getKey! k (modifyKey k f l) = if containsKey k l then k else default := by
|
||
simp [getKey!_modifyKey, hl]
|
||
|
||
theorem getKey_modifyKey [BEq α] [LawfulBEq α] {k k' : α} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) (h : containsKey k' (modifyKey k f l)) :
|
||
getKey k' (modifyKey k f l) h =
|
||
if k == k' then
|
||
k
|
||
else
|
||
haveI h' : containsKey k' l := by rwa [containsKey_modifyKey] at h
|
||
getKey k' l h' := by
|
||
simp only [modifyKey_eq_alterKey, getKey_alterKey, hl, ← dite_eq_ite]
|
||
|
||
@[simp]
|
||
theorem getKey_modifyKey_self [BEq α] [LawfulBEq α] {k : α} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (_ : DistinctKeys l) (h : containsKey k (modifyKey k f l)) :
|
||
getKey k (modifyKey k f l) h = k := by
|
||
simp only [getKey_eq]
|
||
|
||
theorem getKeyD_modifyKey [BEq α] [LawfulBEq α] {k k' fallback : α} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getKeyD k' (modifyKey k f l) fallback =
|
||
if k == k' then
|
||
if containsKey k l then k else fallback
|
||
else
|
||
getKeyD k' l fallback := by
|
||
simp [modifyKey_eq_alterKey, getKeyD_alterKey, containsKey_eq_isSome_getValueCast?, hl]
|
||
|
||
theorem getKeyD_modifyKey_self [BEq α] [LawfulBEq α] {k fallback : α} {f : β k → β k}
|
||
(l : List ((a : α) × β a)) (hl : DistinctKeys l) :
|
||
getKeyD k (modifyKey k f l) fallback = if containsKey k l then k else fallback := by
|
||
simp [getKeyD_modifyKey, hl]
|
||
|
||
namespace Const
|
||
|
||
variable {β : Type v} [BEq α]
|
||
|
||
/-- Internal implementation detail of the hash map -/
|
||
def modifyKey (k : α) (f : β → β)
|
||
(l : List ((_ : α) × β)) : List ((_ : α) × β) :=
|
||
match getValue? k l with
|
||
| none => l
|
||
| some v => replaceEntry k (f v) l
|
||
|
||
theorem isEmpty_modifyKey (k : α) (f : β → β) (l : List ((_ : α) × β)) :
|
||
(modifyKey k f l).isEmpty = l.isEmpty := by
|
||
match l with
|
||
| [] => simp [modifyKey]
|
||
| a :: as =>
|
||
simp only [modifyKey, replaceEntry, cond_eq_ite]
|
||
repeat' split <;> simp
|
||
|
||
theorem modifyKey_eq_alterKey (k : α) (f : β → β) (l : List ((_ : α) × β)) :
|
||
modifyKey k f l = alterKey k (·.map f) l := by
|
||
rw [modifyKey, alterKey, Option.map.eq_def]
|
||
split <;> next h =>
|
||
simp [h, insertEntry, containsKey_eq_isSome_getValue?, eraseKey_of_containsKey_eq_false]
|
||
|
||
theorem modifyKey_of_perm [EquivBEq α] {l l' : List ((_ : α) × β)} {k : α} {f : β → β}
|
||
(hl : DistinctKeys l) (h : Perm l l') :
|
||
Perm (modifyKey k f l) (modifyKey k f l') := by
|
||
simp only [modifyKey_eq_alterKey, alterKey_of_perm hl h]
|
||
|
||
theorem length_modifyKey (k : α) (f : β → β) (l : List ((_ : α) × β)) :
|
||
(modifyKey k f l).length = l.length := by
|
||
induction l
|
||
· rfl
|
||
next ih =>
|
||
simp only [modifyKey]
|
||
split <;> next h => simp only [length_replaceEntry, List.length_cons]
|
||
|
||
theorem containsKey_modifyKey [EquivBEq α] (k k': α) (f : β → β) (l : List ((_ : α) × β)) :
|
||
containsKey k' (modifyKey k f l) = containsKey k' l := by
|
||
induction l
|
||
· simp only [modifyKey, getValue?_nil, containsKey_nil]
|
||
· simp only [modifyKey]
|
||
split
|
||
· rfl
|
||
· rw [containsKey_replaceEntry]
|
||
|
||
theorem getValue?_modifyKey [EquivBEq α] {k k' : α} {f : β → β} (l : List ((_ : α) × β))
|
||
(hl : DistinctKeys l) :
|
||
getValue? k' (modifyKey k f l) =
|
||
if k == k' then
|
||
(getValue? k l).map f
|
||
else
|
||
getValue? k' l := by
|
||
simp [modifyKey_eq_alterKey, getValue?_alterKey, hl]
|
||
|
||
@[simp]
|
||
theorem getValue?_modifyKey_self [EquivBEq α] {k : α} {f : β → β} (l : List ((_ : α) × β))
|
||
(hl : DistinctKeys l) : getValue? k (modifyKey k f l) = (getValue? k l).map f := by
|
||
simp [getValue?_modifyKey, hl]
|
||
|
||
theorem getValue_modifyKey [EquivBEq α] {k k' : α} {f : β → β} (l : List ((_ : α) × β))
|
||
(hl : DistinctKeys l) (h : containsKey k' (modifyKey k f l)) :
|
||
getValue k' (modifyKey k f l) h =
|
||
if heq : k == k' then
|
||
haveI h' : containsKey k l := by rwa [containsKey_modifyKey, ← containsKey_congr heq] at h
|
||
f (getValue k l h')
|
||
else
|
||
haveI h' : containsKey k' l := by rwa [containsKey_modifyKey] at h
|
||
getValue k' l h' := by
|
||
simp only [modifyKey_eq_alterKey, getValue_alterKey, hl]
|
||
split
|
||
next heq =>
|
||
haveI h' : containsKey k l := by rwa [containsKey_modifyKey, ← containsKey_congr heq] at h
|
||
simp [getValue?_eq_some_getValue, h']
|
||
· rfl
|
||
|
||
@[simp]
|
||
theorem getValue_modifyKey_self [EquivBEq α] {k : α} {f : β → β} (l : List ((_ : α) × β))
|
||
(hl : DistinctKeys l) {h : containsKey k (modifyKey k f l)} :
|
||
haveI h' : containsKey k l := by rwa [containsKey_modifyKey] at h
|
||
getValue k (modifyKey k f l) h = f (getValue k l h') := by
|
||
simp [getValue_modifyKey, hl]
|
||
|
||
theorem getValue!_modifyKey [EquivBEq α] {k k' : α} [hi : Inhabited β] {f : β → β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) : getValue! k' (modifyKey k f l) =
|
||
if k == k' then
|
||
getValue? k l |>.map f |>.get!
|
||
else
|
||
getValue! k' l := by
|
||
simp [modifyKey_eq_alterKey, getValue!_alterKey, hl]
|
||
|
||
@[simp]
|
||
theorem getValue!_modifyKey_self [EquivBEq α] {k : α} [Inhabited (β)] {f : β → β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) :
|
||
getValue! k (modifyKey k f l) = ((getValue? k l).map f).get! := by
|
||
simp [getValue!_modifyKey, hl]
|
||
|
||
theorem getValueD_modifyKey [EquivBEq α] {k k' : α} {fallback : β} {f : β → β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) :
|
||
getValueD k' (modifyKey k f l) fallback =
|
||
if k == k' then
|
||
getValue? k l |>.map f |>.getD fallback
|
||
else
|
||
getValueD k' l fallback := by
|
||
simp [modifyKey_eq_alterKey, getValueD_alterKey, hl]
|
||
|
||
@[simp]
|
||
theorem getValueD_modifyKey_self [EquivBEq α] {k : α} {fallback : β} {f : β → β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) :
|
||
getValueD k (modifyKey k f l) fallback = ((getValue? k l).map f).getD fallback := by
|
||
simp [getValueD_modifyKey, hl]
|
||
|
||
theorem getKey?_modifyKey [EquivBEq α] {k k' : α} {f : β → β} (l : List ((_ : α) × β))
|
||
(hl : DistinctKeys l) :
|
||
getKey? k' (modifyKey k f l) =
|
||
if k == k' then
|
||
if containsKey k l then some k else none
|
||
else
|
||
getKey? k' l := by
|
||
simp [modifyKey_eq_alterKey, getKey?_alterKey, containsKey_eq_isSome_getValue?, hl]
|
||
|
||
theorem getKey?_modifyKey_self [EquivBEq α] {k : α} {f : β → β} (l : List ((_ : α) × β))
|
||
(hl : DistinctKeys l) :
|
||
getKey? k (modifyKey k f l) = if containsKey k l then some k else none := by
|
||
simp [getKey?_modifyKey, hl]
|
||
|
||
theorem getKey!_modifyKey [EquivBEq α] [Inhabited α] {k k' : α} {f : β → β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) : getKey! k' (modifyKey k f l) =
|
||
if k == k' then
|
||
if containsKey k l then k else default
|
||
else
|
||
getKey! k' l := by
|
||
simp [modifyKey_eq_alterKey, getKey!_alterKey, containsKey_eq_isSome_getValue?, hl]
|
||
|
||
theorem getKey!_modifyKey_self [EquivBEq α] [Inhabited α] {k : α} {f : β → β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) :
|
||
getKey! k (modifyKey k f l) = if containsKey k l then k else default := by
|
||
simp [getKey!_modifyKey, hl]
|
||
|
||
theorem getKey_modifyKey [EquivBEq α] {k k' : α} {f : β → β} (l : List ((_ : α) × β))
|
||
(hl : DistinctKeys l) (h : containsKey k' (modifyKey k f l)) :
|
||
getKey k' (modifyKey k f l) h =
|
||
if k == k' then
|
||
k
|
||
else
|
||
haveI h' : containsKey k' l := by rwa [containsKey_modifyKey] at h
|
||
getKey k' l h' := by
|
||
simp only [modifyKey_eq_alterKey, getKey_alterKey, hl]
|
||
rfl
|
||
|
||
@[simp]
|
||
theorem getKey_modifyKey_self [EquivBEq α] {k : α} {f : β → β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) (h : containsKey k (modifyKey k f l)) :
|
||
getKey k (modifyKey k f l) h = k := by
|
||
simp [getKey_modifyKey, hl]
|
||
|
||
theorem getKeyD_modifyKey [EquivBEq α] {k k' fallback : α} {f : β → β} (l : List ((_ : α) × β))
|
||
(hl : DistinctKeys l) :
|
||
getKeyD k' (modifyKey k f l) fallback =
|
||
if k == k' then
|
||
if containsKey k l then k else fallback
|
||
else
|
||
getKeyD k' l fallback := by
|
||
simp [modifyKey_eq_alterKey, getKeyD_alterKey, containsKey_eq_isSome_getValue?, hl]
|
||
|
||
theorem getKeyD_modifyKey_self [EquivBEq α] {k fallback : α} {f : β → β}
|
||
(l : List ((_ : α) × β)) (hl : DistinctKeys l) :
|
||
getKeyD k (modifyKey k f l) fallback = if containsKey k l then k else fallback := by
|
||
simp [getKeyD_modifyKey, hl]
|
||
|
||
end Const
|
||
|
||
theorem constModifyKey_eq_modifyKey {β : Type v} [BEq α] [LawfulBEq α] {k : α} {f : β → β}
|
||
{l : List ((_ : α) × β)} :
|
||
Const.modifyKey k f l = modifyKey k f l := by
|
||
rw [modifyKey, Const.modifyKey, getValue?_eq_getValueCast?]
|
||
cases getValueCast? k l <;> rfl
|
||
|
||
theorem DistinctKeys.constModifyKey {β : Type v} [BEq α] [EquivBEq α] {a f} {l : List ((_ : α) × β)}
|
||
(hd : DistinctKeys l) : DistinctKeys (Const.modifyKey a f l) := by
|
||
simpa [Const.modifyKey_eq_alterKey] using hd.constAlterKey
|
||
|
||
end Modify
|
||
|
||
section FilterMap
|
||
|
||
private theorem Option.dmap_bind {α β γ : Type _} (x : Option α) (f : α → Option β)
|
||
(g : (a : β) → x.bind f = some a → γ) :
|
||
Option.dmap (x.bind f) g =
|
||
x.pbind (fun a h => Option.dmap (f a) (fun b h' => g b (h ▸ h'.symm ▸ rfl))) := by
|
||
cases x <;> rfl
|
||
|
||
private theorem Option.bind_dmap_left {α β γ : Type _} (x : Option α)
|
||
(f : (a : α) → x = some a → β) (g : β → Option γ) :
|
||
(Option.dmap x f).bind g = x.pbind (fun a h => g (f a h)) := by
|
||
cases x <;> rfl
|
||
|
||
private theorem Option.dmap_map {α β γ : Type _} (x : Option α) (f : α → β)
|
||
(g : (a : β) → x.map f = some a → γ) :
|
||
Option.dmap (x.map f) g = Option.dmap x (fun a h => g (f a) (h ▸ rfl)) := by
|
||
cases x <;> rfl
|
||
|
||
private theorem Option.map_dmap {α β γ : Type _} (x : Option α)
|
||
(f : (a : α) → x = some a → β) (g : β → γ) :
|
||
(x.dmap f).map g = Option.dmap x (fun a h => g (f a h)) := by
|
||
cases x <;> rfl
|
||
|
||
private theorem Option.dmap_id {α : Type _} (x : Option α) : Option.dmap x (fun a _ => a) = x := by
|
||
cases x <;> rfl
|
||
|
||
private theorem Option.dmap_ite {α β : Type _} (p : Prop) [Decidable p] (t e : Option α)
|
||
(f : (a : α) → (if p then t else e) = some a → β) :
|
||
Option.dmap (if p then t else e) f =
|
||
if h : p then Option.dmap t (fun a h' => f a (if_pos h ▸ h'))
|
||
else Option.dmap e (fun a h' => f a (if_neg h ▸ h')) := by
|
||
split
|
||
· rename_i h
|
||
simp only
|
||
· rename_i h
|
||
simp only
|
||
|
||
private theorem Option.get_dmap {α β : Type _} {x : Option α} {f : (a : α) → x = some a → β} (h) :
|
||
(Option.dmap x f).get h =
|
||
f (x.get (isSome_dmap.symm.trans h)) (Option.eq_some_of_isSome _) := by
|
||
cases x <;> trivial
|
||
|
||
theorem guard_eq_map (p : (a : α) × β a → Prop) [DecidablePred p] :
|
||
Option.guard p = fun x => Option.map (fun y => ⟨x.1, y⟩) (if p x then some x.2 else none) := by
|
||
funext x
|
||
simp [Option.guard]
|
||
|
||
theorem Sigma.snd_congr {x x' : (a : α) × β a} (h : x = x') :
|
||
x.snd = cast (congrArg (β ·.fst) h.symm) x'.snd := by
|
||
cases h; rfl
|
||
|
||
private theorem Option.pmap_eq_dmap {α β : Type _} {p : α → Prop} {x : Option α}
|
||
{f : (a : α) → p a → β} (h : ∀ a ∈ x, p a) :
|
||
x.pmap f h = Option.dmap x (fun a h' => f a (h a h')) := by
|
||
cases x <;> rfl
|
||
|
||
private theorem Option.dmap_eq_map {α β : Type _} {x : Option α} {f : α → β} :
|
||
Option.dmap x (fun a _ => f a) = x.map f := by
|
||
cases x <;> rfl
|
||
|
||
private theorem Option.any_dmap {α β : Type _} {x : Option α}
|
||
{f : (a : α) → x = some a → β} {p : β → Bool} :
|
||
(x.dmap f).any p = x.attach.any (fun ⟨a, h⟩ => p (f a h)) := by
|
||
cases x <;> rfl
|
||
|
||
theorem getEntry?_filterMap' [BEq α] [EquivBEq α]
|
||
{f : ((a : α) × β a) → Option (((a : α) × γ a))}
|
||
(hf : ∀ p, (f p).all (·.1 == p.1))
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getEntry? k (l.filterMap f) = (getEntry? k l).bind f := by
|
||
induction l using assoc_induction with
|
||
| nil => rfl
|
||
| cons k' v l ih =>
|
||
simp only [getEntry?, cond_eq_ite]
|
||
simp only [distinctKeys_cons_iff] at hl
|
||
specialize ih hl.1
|
||
specialize hf ⟨k', v⟩
|
||
split
|
||
· rename_i h
|
||
simp only [List.filterMap_cons, Option.bind_some]
|
||
simp only [containsKey_congr h] at hl
|
||
split
|
||
· simp only [ih, ‹f _ = _›, Option.bind_none, getEntry?_eq_none.mpr hl.2]
|
||
· rw [‹f _ = _›, Option.all_some, BEq.congr_right h] at hf
|
||
rw [getEntry?_cons, hf, ‹f _ = _›, cond_true]
|
||
· simp only [List.filterMap_cons]
|
||
split
|
||
· exact ih
|
||
· rw [‹f _ = _›, Option.all_some] at hf
|
||
rw [getEntry?_cons, BEq.congr_left hf, (Bool.not_eq_true (_ == _)).mp ‹_›, ih, cond_false]
|
||
|
||
theorem getEntry?_map' [BEq α] [EquivBEq α]
|
||
{f : ((a : α) × β a) → ((a : α) × γ a)}
|
||
(hf : ∀ p, (f p).1 == p.1)
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getEntry? k (l.map f) = (getEntry? k l).map f := by
|
||
rw [← List.filterMap_eq_map, getEntry?_filterMap' hf hl, ← Option.map_eq_bind]
|
||
|
||
theorem getEntry?_filter [BEq α] [EquivBEq α]
|
||
{f : ((a : α) × β a) → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getEntry? k (l.filter f) = (getEntry? k l).filter f := by
|
||
rw [← List.filterMap_eq_filter, getEntry?_filterMap' _ hl, Option.bind_guard]
|
||
intro p
|
||
simp only [Option.all_guard, BEq.rfl, Bool.or_true]
|
||
|
||
theorem getEntry?_filterMap [BEq α] [EquivBEq α]
|
||
{f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getEntry? k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩)) =
|
||
(getEntry? k l).bind fun p => (f p.1 p.2).map (⟨p.1, ·⟩) := by
|
||
refine getEntry?_filterMap' ?_ hl
|
||
intro p
|
||
simp [Option.all_eq_true]
|
||
|
||
theorem getEntry?_map [BEq α] [EquivBEq α]
|
||
{f : (a : α) → β a → γ a}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getEntry? k (l.map fun p => ⟨p.1, f p.1 p.2⟩) =
|
||
(getEntry? k l).map fun p => ⟨p.1, f p.1 p.2⟩ := by
|
||
refine getEntry?_map' ?_ hl
|
||
intro p
|
||
exact BEq.rfl
|
||
|
||
theorem containsKey_of_containsKey_filterMap' [BEq α] [EquivBEq α]
|
||
{f : ((a : α) × β a) → Option ((a : α) × γ a)}
|
||
(hf : ∀ p, (f p).all (·.1 == p.1))
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l)
|
||
(h : containsKey k (l.filterMap f)) : containsKey k l := by
|
||
simp only [containsKey_eq_isSome_getEntry?, getEntry?_filterMap' hf hl] at h ⊢
|
||
simp only [Option.isSome_bind, Option.any_eq_true] at h
|
||
obtain ⟨y, hy, _⟩ := h
|
||
exact Option.isSome_of_mem hy
|
||
|
||
theorem containsKey_of_containsKey_filterMap [BEq α] [EquivBEq α]
|
||
{f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l)
|
||
(h : containsKey k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩))) :
|
||
containsKey k l := by
|
||
rw [containsKey_of_containsKey_filterMap' _ hl h]
|
||
intro p
|
||
simp [Option.all_eq_true]
|
||
|
||
theorem snd_eq_getValueCast_of_getEntry?_eq_some [BEq α] [LawfulBEq α]
|
||
{l : List ((a : α) × β a)} {k : α}
|
||
{y : (a : α) × β a} (h : getEntry? k l = some y) :
|
||
y.snd = cast
|
||
(congrArg β (eq_of_beq (beq_of_getEntry?_eq_some h)).symm)
|
||
(getValueCast k l (containsKey_eq_isSome_getEntry?.trans (Option.isSome_of_eq_some h))) := by
|
||
simp only [getValueCast, getValueCast?_eq_getEntry?, Option.get_dmap]
|
||
simp only [Sigma.snd_congr (Option.get_congr h), cast_cast]
|
||
rfl
|
||
|
||
theorem eq_getKey_getValue_of_getEntry?_eq_some [BEq α] [EquivBEq α] {β : Type v}
|
||
{l : List ((_ : α) × β)} {k : α}
|
||
{y : (_ : α) × β} (h : getEntry? k l = some y) :
|
||
haveI h' := containsKey_eq_isSome_getEntry?.trans (Option.isSome_of_eq_some h)
|
||
y = ⟨getKey k l h', getValue k l h'⟩ := by
|
||
simp only [getKey, getKey?_eq_getEntry?, getValue, getValue?_eq_getEntry?, h,
|
||
Option.get_map, Option.get_some]
|
||
|
||
theorem isSome_apply_of_containsKey_filterMap [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l)
|
||
(h : containsKey k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩))) :
|
||
(f k (getValueCast k l (containsKey_of_containsKey_filterMap hl h))).isSome := by
|
||
simp only [containsKey_eq_isSome_getEntry?, getEntry?_filterMap hl] at h
|
||
simp only [Option.isSome_bind, Option.isSome_map, Option.any_eq_true] at h
|
||
obtain ⟨y, (hy : _ = _), hy'⟩ := h
|
||
cases eq_of_beq (beq_of_getEntry?_eq_some hy)
|
||
simpa only [snd_eq_getValueCast_of_getEntry?_eq_some hy] using hy'
|
||
|
||
theorem Const.isSome_apply_of_containsKey_filterMap [BEq α] [EquivBEq α] {β : Type v} {γ : Type w}
|
||
{f : α → β → Option γ}
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l)
|
||
(h : containsKey k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩ : γ → (_ : α) × γ))) :
|
||
haveI h' := containsKey_of_containsKey_filterMap hl h
|
||
(f (getKey k l h') (getValue k l h')).isSome := by
|
||
simp only [containsKey_eq_isSome_getEntry?, getEntry?_filterMap hl] at h
|
||
simp only [Option.isSome_bind, Option.isSome_map, Option.any_eq_true] at h
|
||
obtain ⟨y, (hy : _ = _), hy'⟩ := h
|
||
simpa only [eq_getKey_getValue_of_getEntry?_eq_some hy] using hy'
|
||
|
||
theorem containsKey_of_containsKey_filter [BEq α] [EquivBEq α]
|
||
{f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l)
|
||
(h : containsKey k (l.filter fun p => f p.1 p.2)) :
|
||
containsKey k l := by
|
||
rw [← List.filterMap_eq_filter] at h
|
||
rw [containsKey_of_containsKey_filterMap' _ hl h]
|
||
intro p
|
||
simp only [Option.all_guard, BEq.rfl, Bool.or_true]
|
||
|
||
theorem Const.containsKey_filterMap [BEq α] [EquivBEq α] {β : Type v} {γ : Type w}
|
||
{f : (_ : α) → β → Option γ}
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l) :
|
||
containsKey k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))) =
|
||
if h : containsKey k l
|
||
then (f (getKey k l h) (getValue k l h)).isSome
|
||
else false := by
|
||
simp only [containsKey_eq_isSome_getEntry?, hl, getEntry?_filterMap, getKey, getValue]
|
||
induction l with
|
||
| nil => simp
|
||
| cons hd tl ih =>
|
||
rw [distinctKeys_cons_iff] at hl
|
||
by_cases hdk : hd.1 == k
|
||
· simp [getEntry?, hdk, getKey?, getValue?]
|
||
· simp [getEntry?, hdk, getValue?, getKey?, And.left hl, ih]
|
||
|
||
theorem Const.containsKey_filter [BEq α] [EquivBEq α] {β : Type v}
|
||
{f : (_ : α) → β → Bool}
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l) :
|
||
containsKey k (l.filter fun p => f p.1 p.2) =
|
||
if h : containsKey k l
|
||
then f (getKey k l h) (getValue k l h)
|
||
else false := by
|
||
simp only [containsKey_eq_isSome_getEntry?, hl, getEntry?_filter, getKey, getValue]
|
||
induction l with
|
||
| nil => simp
|
||
| cons hd tl ih =>
|
||
rw [distinctKeys_cons_iff] at hl
|
||
by_cases hdk : hd.1 == k
|
||
· simp [getEntry?, hdk, getKey?, getValue?]
|
||
· simp [getEntry?, hdk, getValue?, getKey?, And.left hl, ih]
|
||
|
||
theorem containsKey_map [BEq α] {f : (a : α) → β a → γ a}
|
||
{l : List ((a : α) × β a)} {k : α} :
|
||
containsKey k (l.map fun p => ⟨p.1, f p.1 p.2⟩) = containsKey k l := by
|
||
induction l with
|
||
| nil => rfl
|
||
| cons hd tl ih => simp only [List.map_cons, containsKey, ih]
|
||
|
||
theorem apply_eq_true_of_containsKey_filter [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l)
|
||
(h : containsKey k (l.filter fun p => f p.1 p.2)) :
|
||
f k (getValueCast k l (containsKey_of_containsKey_filter hl h)) := by
|
||
simp only [containsKey_eq_isSome_getEntry?, getEntry?_filter hl] at h
|
||
simp only [Option.isSome_filter, Option.any_eq_true] at h
|
||
obtain ⟨y, (hy : _ = _), hy'⟩ := h
|
||
cases eq_of_beq (beq_of_getEntry?_eq_some hy)
|
||
simp only [snd_eq_getValueCast_of_getEntry?_eq_some hy] at hy'
|
||
exact hy'
|
||
|
||
theorem getValueCast?_filterMap [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getValueCast? k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩)) =
|
||
(getValueCast? k l).bind (f k) := by
|
||
simp only [getValueCast?_eq_getEntry?, Option.dmap_congr (getEntry?_filterMap hl)]
|
||
simp only [Option.dmap_bind, Option.bind_dmap_left, Option.dmap_map]
|
||
congr; funext a h
|
||
cases eq_of_beq (beq_of_getEntry?_eq_some h)
|
||
simp only [cast_eq, Option.dmap_id]
|
||
|
||
theorem getValueCast!_filterMap [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k : α} [Inhabited (γ k)] (hl : DistinctKeys l) :
|
||
getValueCast! k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩)) =
|
||
((getValueCast? k l).bind (f k)).get! := by
|
||
simp [getValueCast!_eq_getValueCast?, getValueCast?_filterMap hl]
|
||
|
||
theorem getValueCastD_filterMap [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) {fallback : γ k} :
|
||
getValueCastD k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩)) fallback =
|
||
((getValueCast? k l).bind (f k)).getD fallback := by
|
||
simp [getValueCastD_eq_getValueCast?, getValueCast?_filterMap hl]
|
||
|
||
theorem getValueCast?_filter [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getValueCast? k (l.filter fun p => f p.1 p.2) =
|
||
(getValueCast? k l).filter (f k) := by
|
||
simp only [getValueCast?_eq_getEntry?, Option.dmap_congr (getEntry?_filter hl)]
|
||
simp only [← Option.bind_guard]
|
||
simp only [Option.dmap_bind, Option.bind_dmap_left]
|
||
congr; funext a h
|
||
cases eq_of_beq (beq_of_getEntry?_eq_some h)
|
||
simp only [cast_eq, Option.guard, Option.dmap_ite,
|
||
Option.dmap_some, Option.dmap_none, dite_eq_ite]
|
||
|
||
theorem getValueCast!_filter [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} [Inhabited (β k)] (hl : DistinctKeys l) :
|
||
getValueCast! k (l.filter fun p => f p.1 p.2) =
|
||
((getValueCast? k l).filter (f k)).get! := by
|
||
simp [getValueCast!_eq_getValueCast?, getValueCast?_filter hl]
|
||
|
||
theorem getValueCastD_filter [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) {fallback : β k} :
|
||
getValueCastD k (l.filter fun p => f p.1 p.2) fallback =
|
||
((getValueCast? k l).filter (f k)).getD fallback := by
|
||
simp [getValueCastD_eq_getValueCast?, getValueCast?_filter hl]
|
||
|
||
theorem getValueCast?_map [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → γ a}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getValueCast? k (l.map fun p => ⟨p.1, f p.1 p.2⟩) =
|
||
(getValueCast? k l).map (f k) := by
|
||
simp only [getValueCast?_eq_getEntry?, Option.dmap_congr (getEntry?_map hl)]
|
||
simp only [Option.dmap_map, Option.map_dmap]
|
||
congr; funext a h
|
||
cases eq_of_beq (beq_of_getEntry?_eq_some h)
|
||
rfl
|
||
|
||
theorem getValueCast!_map [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → γ a}
|
||
{l : List ((a : α) × β a)} {k : α} [Inhabited (γ k)] (hl : DistinctKeys l) :
|
||
getValueCast! k (l.map fun p => ⟨p.1, f p.1 p.2⟩) =
|
||
((getValueCast? k l).map (f k)).get! := by
|
||
simp [getValueCast!_eq_getValueCast?, getValueCast?_map hl]
|
||
|
||
theorem getValueCastD_map [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → γ a}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) {fallback : γ k} :
|
||
getValueCastD k (l.map fun p => ⟨p.1, f p.1 p.2⟩) fallback =
|
||
((getValueCast? k l).map (f k)).getD fallback := by
|
||
simp [getValueCastD_eq_getValueCast?, getValueCast?_map hl]
|
||
|
||
theorem getValueCast_filterMap [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) (h) :
|
||
getValueCast k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩)) h =
|
||
(f k (getValueCast k l (containsKey_of_containsKey_filterMap hl h))).get
|
||
(isSome_apply_of_containsKey_filterMap hl h) := by
|
||
simp only [getValueCast, getValueCast?_filterMap hl, Option.get_bind]
|
||
|
||
theorem getValueCast_filter [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) (h) :
|
||
getValueCast k (l.filter fun p => f p.1 p.2) h =
|
||
getValueCast k l (containsKey_of_containsKey_filter hl h) := by
|
||
simp only [getValueCast, getValueCast?_filter hl, Option.get_filter]
|
||
|
||
theorem getValueCast_map [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → γ a}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) (h) :
|
||
getValueCast k (l.map fun p => ⟨p.1, f p.1 p.2⟩) h =
|
||
f k (getValueCast k l (containsKey_map.symm.trans h)) := by
|
||
simp only [getValueCast, getValueCast?_map hl, Option.get_map]
|
||
|
||
theorem containsKey_filterMap [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
containsKey k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩)) =
|
||
(getValueCast? k l).any (f k · |>.isSome) := by
|
||
simp only [containsKey_eq_isSome_getValueCast?, getValueCast?_filterMap hl, Option.isSome_bind]
|
||
|
||
theorem containsKey_filter [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
containsKey k (l.filter fun p => f p.1 p.2) =
|
||
(getValueCast? k l).any (f k) := by
|
||
simp only [containsKey_eq_isSome_getValueCast?, getValueCast?_filter hl, Option.isSome_filter]
|
||
|
||
theorem containsKey_filter_key [BEq α] [EquivBEq α]
|
||
{f : α → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
containsKey k (l.filter fun p => f p.1) ↔ ∃ h : containsKey k l, f (getKey k l h) := by
|
||
simp only [containsKey_eq_isSome_getEntry?, getEntry?_filter hl, Option.isSome_filter,
|
||
Option.any_eq_true_iff_get, getKey, getKey?_eq_getEntry?, Option.get_map]
|
||
|
||
theorem Option.exists_eq_some_and_iff (o : Option α) (p : α → Prop) :
|
||
(∃ x, o = some x ∧ p x) ↔ ∃ h : o.isSome, p (o.get h) := by
|
||
cases o <;> simp
|
||
|
||
theorem containsKey_filterMap_iff [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
containsKey k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩)) ↔
|
||
∃ h : containsKey k l, (f k (getValueCast k l h)).isSome := by
|
||
simp only [containsKey_filterMap hl, Option.any_eq_true, getValueCast,
|
||
Option.exists_eq_some_and_iff, containsKey_eq_isSome_getValueCast?]
|
||
|
||
theorem containsKey_filter_iff [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
containsKey k (l.filter fun p => f p.1 p.2) ↔
|
||
∃ h : containsKey k l, f k (getValueCast k l h) := by
|
||
simp only [containsKey_filter hl, Option.any_eq_true, getValueCast,
|
||
Option.exists_eq_some_and_iff, containsKey_eq_isSome_getValueCast?]
|
||
|
||
theorem Const.containsKey_filterMap_iff {β : Type v} {γ : Type w}
|
||
[BEq α] [EquivBEq α]
|
||
{f : α → β → Option γ}
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l) :
|
||
containsKey k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩ : γ → (_ : α) × γ)) ↔
|
||
∃ h : containsKey k l, (f (getKey k l h) (getValue k l h)).isSome := by
|
||
simp only [containsKey_eq_isSome_getEntry?, getEntry?_filterMap hl,
|
||
Option.isSome_bind, Option.any_eq_true, Option.isSome_map,
|
||
Option.exists_eq_some_and_iff, getKey, getValue, getKey?_eq_getEntry?,
|
||
getValue?_eq_getEntry?, Option.get_map]
|
||
|
||
theorem Const.containsKey_filter_iff {β : Type v} [BEq α] [EquivBEq α]
|
||
{f : α → β → Bool}
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l) :
|
||
containsKey k (l.filter fun p => f p.1 p.2) ↔
|
||
∃ h : containsKey k l, f (getKey k l h) (getValue k l h) := by
|
||
simp only [containsKey_eq_isSome_getEntry?, getEntry?_filter hl,
|
||
Option.isSome_filter, Option.any_eq_true, Option.exists_eq_some_and_iff,
|
||
getKey, getValue, getKey?_eq_getEntry?, getValue?_eq_getEntry?, Option.get_map]
|
||
|
||
theorem getKey?_filterMap [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getKey? k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (a : α) × γ a))) =
|
||
(getKey? k l).pfilter (fun x h =>
|
||
(f x (getValueCast x l (containsKey_of_getKey?_eq_some h))).isSome) := by
|
||
simp only [getKey?_eq_getEntry?, getEntry?_filterMap hl, getValueCast,
|
||
getValueCast?_eq_getEntry?, Option.map_bind, Function.comp_def,
|
||
Option.map_map, Option.pfilter_eq_pbind_ite, Option.pbind_map]
|
||
rw [← Option.pbind_eq_bind]
|
||
congr; funext a h
|
||
cases eq_of_beq (beq_of_getEntry?_eq_some h)
|
||
simp only [show _ = _ from h, Option.dmap_some, Option.get_some, cast_eq]
|
||
cases f a.1 a.2 <;> rfl
|
||
|
||
theorem getKey!_filterMap [BEq α] [LawfulBEq α] [Inhabited α]
|
||
{f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getKey! k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (a : α) × γ a))) =
|
||
((getKey? k l).pfilter (fun x h =>
|
||
(f x (getValueCast x l (containsKey_of_getKey?_eq_some (Option.mem_def.mp h)))).isSome)).get! := by
|
||
simp [getKey!_eq_getKey?, getKey?_filterMap hl]
|
||
|
||
theorem getKeyD_filterMap [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k fallback : α} (hl : DistinctKeys l) :
|
||
getKeyD k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (a : α) × γ a))) fallback =
|
||
((getKey? k l).pfilter (fun x h =>
|
||
(f x (getValueCast x l (containsKey_of_getKey?_eq_some (Option.mem_def.mp h)))).isSome)).getD fallback := by
|
||
simp [getKeyD_eq_getKey?, getKey?_filterMap hl]
|
||
|
||
theorem getValueCast_eq_get_getValueCast? [BEq α] [LawfulBEq α] {a : α} {l : List ((a : α) × β a)}
|
||
{h : containsKey a l} :
|
||
getValueCast a l h = (getValueCast? a l).get (containsKey_eq_isSome_getValueCast? (a := a) ▸ h) := by
|
||
simp [getValueCast?_eq_some_getValueCast 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)
|
||
{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 getKey?_filter [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getKey? k (l.filter fun p => f p.1 p.2) =
|
||
(getKey? k l).pfilter (fun x h =>
|
||
(f x (getValueCast x l (containsKey_of_getKey?_eq_some (Option.mem_def.mp h))))) := by
|
||
simp [getKey?_eq_getEntry?, getEntry?_filter hl, getValueCast_eq_get_getValueCast?,
|
||
getValueCast?_eq_getEntry?]
|
||
obtain (h|⟨p, h⟩) := Option.eq_none_or_eq_some (getEntry? k l)
|
||
· simp [h]
|
||
· cases eq_of_beq (beq_of_getEntry?_eq_some h)
|
||
simp [h, Option.filter_some]
|
||
|
||
theorem getKey?_filter_key [BEq α] [EquivBEq α]
|
||
{f : α → Bool} {l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getKey? k (l.filter fun p => f p.1) = (getKey? k l).filter f := by
|
||
induction l using assoc_induction with
|
||
| nil => rfl
|
||
| cons k' v t ih =>
|
||
specialize ih hl.tail
|
||
simp only [getKey?_cons, List.filter_cons]
|
||
split
|
||
· simp only [getKey?_cons, ih, cond_eq_ite, apply_ite (Option.filter f), Option.filter_some,
|
||
‹f k'›, ↓reduceIte]
|
||
· replace hl := hl.containsKey_eq_false
|
||
simp only [ih, cond_eq_ite]
|
||
split
|
||
· rw [containsKey_congr ‹_›] at hl
|
||
simp only [getKey?_eq_none hl, Option.filter_none, Option.filter_some, eq_false ‹_›,
|
||
↓reduceIte]
|
||
· rfl
|
||
|
||
theorem getKey!_filter [BEq α] [LawfulBEq α] [Inhabited α]
|
||
{f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getKey! k (l.filter fun p => f p.1 p.2) =
|
||
((getKey? k l).pfilter (fun x h =>
|
||
(f x (getValueCast x l (containsKey_of_getKey?_eq_some (Option.mem_def.mp h)))))).get! := by
|
||
simp [getKey!_eq_getKey?, getKey?_filter hl]
|
||
|
||
theorem getKey!_filter_key [BEq α] [EquivBEq α] [Inhabited α]
|
||
{f : α → Bool} {l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getKey! k (l.filter fun p => f p.1) = ((getKey? k l).filter f).get! := by
|
||
simp [getKey!_eq_getKey?, getKey?_filter_key hl]
|
||
|
||
theorem getKeyD_filter [BEq α] [LawfulBEq α]
|
||
{f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} {k fallback : α} (hl : DistinctKeys l) :
|
||
getKeyD k (l.filter fun p => (f p.1 p.2)) fallback =
|
||
((getKey? k l).pfilter (fun x h =>
|
||
(f x (getValueCast x l (containsKey_of_getKey?_eq_some (Option.mem_def.mp h)))))).getD fallback := by
|
||
simp [getKeyD_eq_getKey?, getKey?_filter hl]
|
||
|
||
theorem getKeyD_filter_key [BEq α] [EquivBEq α]
|
||
{f : α → Bool} {l : List ((a : α) × β a)} {k fallback : α} (hl : DistinctKeys l) :
|
||
getKeyD k (l.filter fun p => f p.1) fallback = ((getKey? k l).filter f).getD fallback := by
|
||
simp [getKeyD_eq_getKey?, getKey?_filter_key hl]
|
||
|
||
theorem getKey?_map [BEq α] [EquivBEq α] {f : (a : α) → β a → γ a}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getKey? k (l.map fun p => ⟨p.1, f p.1 p.2⟩) = getKey? k l := by
|
||
simp only [getKey?_eq_getEntry?, getEntry?_map hl, Option.map_map, Function.comp_def]
|
||
|
||
theorem getKey_map [BEq α] [EquivBEq α] {f : (a : α) → β a → γ a}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) {h} :
|
||
getKey k (l.map fun p => ⟨p.1, f p.1 p.2⟩) h = getKey k l (containsKey_map.symm.trans h) := by
|
||
simp only [getKey, getKey?_map hl]
|
||
|
||
theorem getKey!_map [BEq α] [EquivBEq α] [Inhabited α] {f : (a : α) → β a → γ a}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) :
|
||
getKey! k (l.map fun p => ⟨p.1, f p.1 p.2⟩) = getKey! k l := by
|
||
simp only [getKey!_eq_getKey?, getKey?_map hl]
|
||
|
||
theorem getKeyD_map [BEq α] [EquivBEq α] {f : (a : α) → β a → γ a}
|
||
{l : List ((a : α) × β a)} {k : α} {fallback : α} (hl : DistinctKeys l) :
|
||
getKeyD k (l.map fun p => ⟨p.1, f p.1 p.2⟩) fallback = getKeyD k l fallback := by
|
||
simp only [getKeyD_eq_getKey?, getKey?_map hl]
|
||
|
||
theorem getKey_filterMap [BEq α] [EquivBEq α] {f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) {h} :
|
||
getKey k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩)) h =
|
||
getKey k l (containsKey_of_containsKey_filterMap hl h) := by
|
||
simp only [getKey, getKey?_eq_getEntry?, getEntry?_filterMap hl, Option.get_map, Option.get_bind]
|
||
|
||
theorem getKey_filter [BEq α] [EquivBEq α] {f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} {k : α} (hl : DistinctKeys l) {h} :
|
||
getKey k (l.filter fun p => f p.1 p.2) h =
|
||
getKey k l (containsKey_of_containsKey_filter hl h) := by
|
||
simp only [getKey, getKey?_eq_getEntry?, getEntry?_filter hl, Option.get_map, Option.get_filter]
|
||
|
||
theorem getValue_map [BEq α] [EquivBEq α] {β : Type v} {γ : Type w}
|
||
{f : α → β → γ}
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l) {h} :
|
||
getValue k (l.map fun p => ⟨p.1, f p.1 p.2⟩) h =
|
||
haveI h' := containsKey_map.symm.trans h
|
||
f (getKey k l h') (getValue k l h') := by
|
||
simp only [getKey, getKey?_eq_getEntry?, getValue, getValue?_eq_getEntry?, getEntry?_map hl,
|
||
Option.get_map]
|
||
|
||
theorem getValue_filterMap [BEq α] [EquivBEq α] {β : Type v} {γ : Type w}
|
||
{f : α → β → Option γ}
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l) {h} :
|
||
getValue k (l.filterMap fun p => (f p.1 p.2).map (⟨p.1, ·⟩ : γ → (_ : α) × γ)) h =
|
||
haveI h' := containsKey_of_containsKey_filterMap hl h
|
||
haveI h'' := Const.isSome_apply_of_containsKey_filterMap hl h
|
||
(f (getKey k l h') (getValue k l h')).get h'' := by
|
||
simp only [getKey, getKey?_eq_getEntry?, getValue, getValue?_eq_getEntry?,
|
||
getEntry?_filterMap hl, Option.get_map, Option.get_bind]
|
||
|
||
theorem getValue_filter [BEq α] [EquivBEq α] {β : Type v} {f : α → β → Bool}
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l) {h} :
|
||
getValue k (l.filter fun p => f p.1 p.2) h =
|
||
getValue k l (containsKey_of_containsKey_filter hl h) := by
|
||
simp only [getValue, getValue?_eq_getEntry?, getEntry?_filter hl,
|
||
Option.get_map, Option.get_filter]
|
||
|
||
theorem length_filterMap_eq_length_iff [BEq α] [LawfulBEq α] {f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} (distinct : DistinctKeys l) :
|
||
(l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (a : α) × γ a))).length = l.length ↔
|
||
∀ (a : α) (h : containsKey a l), (f a (getValueCast a l h)).isSome := by
|
||
rw [List.filterMap_length_eq_length]
|
||
constructor
|
||
· intro h a ha
|
||
specialize h ⟨a, getValueCast a l ha⟩
|
||
simp only [Option.isSome_map] at h
|
||
apply h
|
||
apply getValueCast_mem
|
||
· intro h x hx
|
||
simp only [Option.isSome_map]
|
||
specialize h x.1 (containsKey_of_mem hx)
|
||
rw [getValueCast_of_mem hx distinct] at h
|
||
exact h
|
||
|
||
theorem key_getValueCast_mem [BEq α] [LawfulBEq α]
|
||
{l : List ((a : α) × β a)} {a : α} (h : containsKey a l = true) :
|
||
⟨a, getValueCast a l h⟩ ∈ l := by
|
||
induction l with
|
||
| nil => simp at h
|
||
| cons hd tl ih =>
|
||
by_cases hd_a : hd.1 == a
|
||
· simp [getValueCast, getValueCast?, Sigma.ext_iff, LawfulBEq.eq_of_beq hd_a]
|
||
· rw [containsKey_cons] at h
|
||
simp only [hd_a, Bool.false_or] at h
|
||
simp only [getValueCast, getValueCast?, hd_a, Bool.false_eq_true, ↓reduceDIte, List.mem_cons]
|
||
exact Or.inr (ih h)
|
||
|
||
theorem forall_mem_iff_forall_contains_getValueCast [BEq α] [LawfulBEq α]
|
||
{l : List ((a : α) × β a)} {p : (a : α) → β a → Prop} (distinct : DistinctKeys l) :
|
||
(∀ (x : (a : α) × β a), x ∈ l → p x.1 x.2) ↔
|
||
∀ (a: α) (h : containsKey a l), p a (getValueCast a l h) := by
|
||
constructor
|
||
· intro h a ha
|
||
specialize h ⟨a, getValueCast a l ha⟩
|
||
apply h (key_getValueCast_mem ha)
|
||
· intro h x hx
|
||
rw [← getValueCast_of_mem hx distinct]
|
||
apply h
|
||
|
||
theorem length_filter_eq_length_iff [BEq α] [LawfulBEq α] {f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} (distinct : DistinctKeys l) :
|
||
(l.filter fun p => f p.1 p.2).length = l.length ↔
|
||
∀ (a : α) (h : containsKey a l), (f a (getValueCast a l h)) = true := by
|
||
simp [← List.filterMap_eq_filter,
|
||
forall_mem_iff_forall_contains_getValueCast (p := fun a b => f a b = true) distinct]
|
||
|
||
theorem length_filter_key_eq_length_iff [BEq α] [EquivBEq α] {f : α → Bool}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
(l.filter fun p => f p.1).length = l.length ↔
|
||
∀ (a : α) (h : containsKey a l), f (getKey a l h) := by
|
||
simp only [_root_.List.length_filter_eq_length_iff]
|
||
constructor
|
||
· intro h a ha
|
||
specialize h (getEntry a l ha) getEntry_mem
|
||
simp only [getKey, getKey?_eq_getEntry?, Option.get_map]
|
||
exact h
|
||
· intro h ⟨k, v⟩ he
|
||
have := getEntry?_of_mem hl BEq.rfl he
|
||
specialize h k (containsKey_eq_isSome_getEntry?.trans (Option.isSome_of_eq_some this))
|
||
simp only [getKey, getKey?_eq_getEntry?, this] at h
|
||
exact h
|
||
|
||
theorem perm_filter_self_iff {f : α → Bool} {l : List α} :
|
||
(l.filter f).Perm l ↔ ∀ a ∈ l, f a = true := by
|
||
rw (occs := [1]) [← (List.filter_append_perm f _).congr_right,
|
||
← List.append_nil (List.filter _ _), List.perm_append_left_iff]
|
||
simp
|
||
|
||
theorem perm_filter_self_iff_forall_containsKey [BEq α] [LawfulBEq α] {f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
List.Perm (l.filter fun p => f p.1 p.2) l ↔ ∀ (a : α) (h : containsKey a l),
|
||
(f a (getValueCast a l h)) = true := by
|
||
rw [perm_filter_self_iff]
|
||
constructor
|
||
· intro h a ha
|
||
exact h _ (getValueCast_mem ha)
|
||
· intro h a ha
|
||
exact getValueCast_of_mem ha hl ▸ h _ (containsKey_of_mem ha)
|
||
|
||
theorem perm_filter_key_self_iff_forall_containsKey [BEq α] [EquivBEq α] {f : α → Bool}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
List.Perm (l.filter fun p => f p.1) l ↔ ∀ (a : α) (h : containsKey a l),
|
||
f (getKey a l h) = true := by
|
||
rw [perm_filter_self_iff]
|
||
constructor
|
||
· intro h a ha
|
||
rw [getKey_eq_getEntry_fst]
|
||
exact h _ getEntry_mem
|
||
· intro h a ha
|
||
simp only [getKey_eq_getEntry_fst] at h
|
||
exact getEntry_of_mem ha hl ▸ h _ (containsKey_of_mem ha)
|
||
|
||
theorem Const.perm_filter_self_iff_forall_containsKey [BEq α] [EquivBEq α] {β : Type v} {f : α → β → Bool}
|
||
{l : List ((_ : α) × β)} (hl : DistinctKeys l) :
|
||
List.Perm (l.filter fun p => f p.1 p.2) l ↔ ∀ (a : α) (h : containsKey a l),
|
||
(f (getKey a l h) (getValue a l h)) = true := by
|
||
rw [perm_filter_self_iff]
|
||
constructor
|
||
· intro h a ha
|
||
simp only [getKey_eq_getEntry_fst, getValue_eq_getEntry_snd]
|
||
exact h _ getEntry_mem
|
||
· intro h a ha
|
||
specialize h a.fst (containsKey_of_mem ha)
|
||
simp only [ha, hl, getKey_of_mem, getValue_of_mem] at h
|
||
exact h
|
||
|
||
theorem isEmpty_filterMap_eq_true [BEq α] [LawfulBEq α] {f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} (distinct : DistinctKeys l) :
|
||
(l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (a : α) × γ a))).isEmpty = true ↔
|
||
∀ (k : α) (h : containsKey k l = true), f k (getValueCast k l h) = none := by
|
||
simp only [List.isEmpty_iff, List.filterMap_eq_nil_iff, Option.map_eq_none_iff,
|
||
forall_mem_iff_forall_contains_getValueCast (p:= fun a b => f a b = none) distinct]
|
||
|
||
theorem isEmpty_filterMap_eq_false [BEq α] [LawfulBEq α] {f : (a : α) → β a → Option (γ a)}
|
||
{l : List ((a : α) × β a)} (distinct : DistinctKeys l) :
|
||
(l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (a : α) × γ a))).isEmpty = false ↔
|
||
∃ (k : α) (h : containsKey k l = true), (f k (getValueCast k l h)).isSome := by
|
||
rw [Bool.eq_false_iff, Ne.eq_1, isEmpty_filterMap_eq_true distinct]
|
||
simp [Option.ne_none_iff_isSome]
|
||
|
||
theorem isEmpty_filter_eq_true [BEq α] [LawfulBEq α] {f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} (distinct : DistinctKeys l) :
|
||
(l.filter fun p => f p.1 p.2).isEmpty = true ↔
|
||
∀ (k : α) (h : containsKey k l = true), f k (getValueCast k l h) = false := by
|
||
simp only [List.isEmpty_iff, List.filter_eq_nil_iff, Bool.not_eq_true,
|
||
forall_mem_iff_forall_contains_getValueCast (p := fun a b => f a b = false) distinct]
|
||
|
||
theorem isEmpty_filter_eq_false [BEq α] [LawfulBEq α] {f : (a : α) → β a → Bool}
|
||
{l : List ((a : α) × β a)} (distinct : DistinctKeys l) :
|
||
(l.filter fun p => (f p.1 p.2)).isEmpty = false ↔
|
||
∃ (k : α) (h : containsKey k l = true), f k (getValueCast k l h) = true := by
|
||
rw [← Bool.not_eq_true, isEmpty_filter_eq_true distinct]
|
||
simp
|
||
|
||
theorem isEmpty_filter_key_iff [BEq α] [EquivBEq α] {f : α → Bool}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
(l.filter fun p => f p.1).isEmpty ↔ ∀ (k : α) (h : containsKey k l), f (getKey k l h) = false := by
|
||
simp only [List.isEmpty_iff, List.filter_eq_nil_iff, Bool.not_eq_true]
|
||
constructor
|
||
· intro h a ha
|
||
specialize h (getEntry a l ha) getEntry_mem
|
||
simp only [getKey, getKey?_eq_getEntry?, Option.get_map]
|
||
exact h
|
||
· intro h ⟨k, v⟩ he
|
||
have := getEntry?_of_mem hl BEq.rfl he
|
||
specialize h k (containsKey_eq_isSome_getEntry?.trans (Option.isSome_of_eq_some this))
|
||
simp only [getKey, getKey?_eq_getEntry?, this] at h
|
||
exact h
|
||
|
||
namespace Const
|
||
|
||
theorem getKey_getValue_mem [BEq α] [EquivBEq α] {β : Type v} {l : List ((_ : α) × β)} {k : α} {h} :
|
||
⟨getKey k l h, getValue k l h⟩ ∈ l := by
|
||
induction l with
|
||
| nil => simp at h
|
||
| cons hd tl ih =>
|
||
by_cases hd_k : hd.1 == k
|
||
· rw [getKey_cons, getValue_cons]
|
||
simp [hd_k]
|
||
· rw [getKey_cons, getValue_cons]
|
||
simp [hd_k, ih]
|
||
|
||
theorem forall_mem_iff_forall_contains_getKey_getValue [BEq α] [EquivBEq α] {β : Type v}
|
||
{l : List ((_ : α) × β)} {p : α → β → Prop} (distinct : DistinctKeys l) :
|
||
(∀ (x : (_ : α) × β), x ∈ l → p x.1 x.2) ↔
|
||
∀ (a: α) (h : containsKey a l), p (getKey a l h) (getValue a l h) := by
|
||
constructor
|
||
· intro h a ha
|
||
specialize h ⟨getKey a l ha, getValue a l ha⟩
|
||
apply h getKey_getValue_mem
|
||
· intro h x hx
|
||
rw [← getKey_of_mem hx distinct (h':=containsKey_of_mem hx),
|
||
← getValue_of_mem hx distinct (h':=containsKey_of_mem hx)]
|
||
apply h
|
||
|
||
theorem getValue?_filterMap {β : Type v} {γ : Type w} [BEq α] [EquivBEq α]
|
||
{f : (_ : α) → β → Option γ} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) {k : α} :
|
||
getValue? k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))) =
|
||
(getValue? k l).pbind (fun v h =>
|
||
f (getKey k l (containsKey_eq_isSome_getValue?.trans (Option.isSome_of_eq_some h))) v) := by
|
||
simp only [getValue?_eq_getEntry?, getEntry?_filterMap distinct,
|
||
Function.comp_def, Option.map_bind, Option.pbind_map,
|
||
Option.map_map, Option.map_id']
|
||
simp only [getKey, getKey?_eq_getEntry?, ← Option.pbind_eq_bind]
|
||
congr; funext a h
|
||
simp only [Option.mem_def.mp h, Option.map_some, Option.get_some]
|
||
|
||
theorem getValue?_filterMap_of_getKey?_eq_some {β : Type v} {γ : Type w} [BEq α] [EquivBEq α]
|
||
{f : (_ : α) → β → Option γ} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) {k k' : α} :
|
||
getKey? k l = some k' →
|
||
getValue? k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))) =
|
||
(getValue? k l).bind (fun x => f k' x) := by
|
||
simp only [getKey?_eq_getEntry?, Option.map_eq_some_iff, getValue?_eq_getEntry?,
|
||
getEntry?_filterMap distinct, Option.map_bind, forall_exists_index, and_imp]
|
||
intro x hx hk
|
||
simp only [hx, Option.bind_some, Function.comp_apply, hk, Option.map_map, Option.map_some]
|
||
cases f k' x.2 <;> simp
|
||
|
||
theorem getValue!_filterMap {β : Type v} {γ : Type w} [BEq α] [EquivBEq α] [Inhabited γ]
|
||
{f : (_ : α) → β → Option γ} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) {k : α} :
|
||
getValue! k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))) =
|
||
((getValue? k l).pbind (fun v h =>
|
||
f (getKey k l (containsKey_eq_isSome_getValue?.trans (Option.isSome_of_eq_some h))) v)).get! := by
|
||
simp only [getValue!_eq_getValue?, getValue?_filterMap distinct]
|
||
|
||
theorem getValue!_filterMap_of_getKey?_eq_some {β : Type v} {γ : Type w} [BEq α] [EquivBEq α]
|
||
[Inhabited γ] {f : (_ : α) → β → Option γ} {l : List ((_ : α) × β)} (distinct : DistinctKeys l)
|
||
{k k' : α} :
|
||
getKey? k l = some k' →
|
||
getValue! k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))) =
|
||
((getValue? k l).bind (fun x => f k' x)).get! := by
|
||
intro h
|
||
simp [getValue!_eq_getValue?, getValue?_filterMap_of_getKey?_eq_some distinct h]
|
||
|
||
theorem getValueD_filterMap {β : Type v} {γ : Type w} [BEq α] [EquivBEq α] {fallback : γ}
|
||
{f : (_ : α) → β → Option γ} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) {k : α} :
|
||
getValueD k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))) fallback =
|
||
((getValue? k l).pbind (fun v h =>
|
||
f (getKey k l (containsKey_eq_isSome_getValue?.trans (Option.isSome_of_eq_some h))) v)).getD fallback := by
|
||
simp [getValueD_eq_getValue?, Option.getD, getValue?_filterMap, distinct]
|
||
|
||
theorem getValueD_filterMap_of_getKey?_eq_some {β : Type v} {γ : Type w} [BEq α] [EquivBEq α]
|
||
{f : (_ : α) → β → Option γ} {l : List ((_ : α) × β)} (distinct : DistinctKeys l)
|
||
{k k' : α} {fallback : γ} :
|
||
getKey? k l = some k' →
|
||
getValueD k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))) fallback =
|
||
((getValue? k l).bind (fun x => f k' x)).getD fallback := by
|
||
intro h
|
||
simp [getValueD_eq_getValue?, getValue?_filterMap_of_getKey?_eq_some distinct h]
|
||
|
||
theorem getValue?_filter {β : Type v} [BEq α] [EquivBEq α]
|
||
{f : (_ : α) → β → Bool} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) {k : α} :
|
||
getValue? k (l.filter fun p => (f p.1 p.2)) =
|
||
(getValue? k l).pfilter (fun v h =>
|
||
f (getKey k l (containsKey_eq_isSome_getValue?.trans (Option.isSome_of_eq_some h))) v) := by
|
||
simp only [getValue?_eq_getEntry?, distinct, getEntry?_filter,
|
||
Option.pfilter_eq_pbind_ite, ← Option.bind_guard, Option.guard_def,
|
||
Option.pbind_map, Option.map_bind, Function.comp_def, apply_ite,
|
||
Option.map_some, Option.map_none]
|
||
simp only [getKey, getKey?_eq_getEntry?, ← Option.pbind_eq_bind]
|
||
congr; funext a h
|
||
simp only [Option.mem_def.mp h, Option.map_some, Option.get_some]
|
||
|
||
theorem getValue?_filter_of_getKey?_eq_some {β : Type v} [BEq α] [EquivBEq α]
|
||
{f : (_ : α) → β → Bool} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) {k k' : α} :
|
||
getKey? k l = some k' →
|
||
getValue? k (l.filter fun p => (f p.1 p.2)) =
|
||
(getValue? k l).filter (fun x => f k' x) := by
|
||
simp only [getKey?_eq_getEntry?, Option.map_eq_some_iff, getValue?_eq_getEntry?,
|
||
getEntry?_filter distinct, forall_exists_index, and_imp]
|
||
intro x hx hk
|
||
simp only [hx, Option.map_some, Option.filter_some, ← hk]
|
||
split <;> simp
|
||
|
||
theorem getValue!_filter {β : Type v} [BEq α] [EquivBEq α] [Inhabited β]
|
||
{f : (_ : α) → β → Bool} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) {k : α} :
|
||
getValue! k (l.filter fun p => (f p.1 p.2)) =
|
||
((getValue? k l).pfilter (fun v h =>
|
||
f (getKey k l (containsKey_eq_isSome_getValue?.trans (Option.isSome_of_eq_some h))) v)).get! := by
|
||
simp [getValue!_eq_getValue?, getValue?_filter, distinct]
|
||
|
||
theorem getValue!_filter_of_getKey?_eq_some {β : Type v} [BEq α] [EquivBEq α] [Inhabited β]
|
||
{f : (_ : α) → β → Bool} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) {k k' : α} :
|
||
getKey? k l = some k' →
|
||
getValue! k (l.filter fun p => (f p.1 p.2)) =
|
||
((getValue? k l).filter (fun x => f k' x)).get! := by
|
||
intro h
|
||
simp [getValue!_eq_getValue?, getValue?_filter_of_getKey?_eq_some distinct h]
|
||
|
||
theorem getValueD_filter {β : Type v} [BEq α] [EquivBEq α] {fallback : β}
|
||
{f : (_ : α) → β → Bool} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) {k : α} :
|
||
getValueD k (l.filter fun p => (f p.1 p.2)) fallback =
|
||
((getValue? k l).pfilter (fun v h =>
|
||
f (getKey k l (containsKey_eq_isSome_getValue?.trans (Option.isSome_of_eq_some h))) v)).getD fallback := by
|
||
simp [getValueD_eq_getValue?, Option.getD, getValue?_filter, distinct]
|
||
|
||
theorem getValueD_filter_of_getKey?_eq_some {β : Type v} [BEq α] [EquivBEq α] {fallback : β}
|
||
{f : (_ : α) → β → Bool} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) {k k' : α}
|
||
(h : getKey? k l = some k') :
|
||
getValueD k (l.filter fun p => (f p.1 p.2)) fallback =
|
||
((getValue? k l).filter (fun x => f k' x)).getD fallback := by
|
||
simp [getValueD_eq_getValue?, getValue?_filter_of_getKey?_eq_some distinct h]
|
||
|
||
theorem getValue?_map {β : Type v} {γ : Type w} [BEq α] [EquivBEq α]
|
||
{f : (_ : α) → β → γ} {l : List ((_ : α) × β)} (hl : DistinctKeys l) {k : α} :
|
||
getValue? k (l.map fun p => ⟨p.1, f p.1 p.2⟩) =
|
||
(getValue? k l).pmap (fun v h => f (getKey k l h) v)
|
||
(fun _ h => containsKey_eq_isSome_getValue?.trans (Option.isSome_of_mem h)) := by
|
||
simp only [getValue?_eq_getEntry?, getEntry?_map hl, Option.map_map, Function.comp_def,
|
||
getKey, getKey?_eq_getEntry?, Option.get_map, Option.pmap_eq_dmap, Option.dmap_map]
|
||
conv => enter [2, 2, a, h]; simp only [h, Option.get_some]
|
||
rw [Option.dmap_eq_map]
|
||
|
||
theorem getValue?_map_of_getKey?_eq_some {β : Type v} {γ : Type w} [BEq α] [EquivBEq α]
|
||
{f : (_ : α) → β → γ} {l : List ((_ : α) × β)} (hl : DistinctKeys l) {k k' : α}
|
||
(h : getKey? k l = some k') :
|
||
getValue? k (l.map fun p => ⟨p.1, f p.1 p.2⟩) = (getValue? k l).map (f k') := by
|
||
simp only [getValue?_map hl, getKey, h, Option.get_some, Option.pmap_eq_map]
|
||
|
||
theorem getValue!_map {β : Type v} {γ : Type w} [BEq α] [EquivBEq α] [Inhabited γ]
|
||
{f : (_ : α) → β → γ} {l : List ((_ : α) × β)} (hl : DistinctKeys l) {k : α} :
|
||
getValue! k (l.map fun p => ⟨p.1, f p.1 p.2⟩) =
|
||
((getValue? k l).pmap (fun v h => f (getKey k l h) v)
|
||
(fun _ h => containsKey_eq_isSome_getValue?.trans (Option.isSome_of_mem h))).get! := by
|
||
simp only [getValue!, getValue?_map hl]
|
||
|
||
theorem getValue!_map_of_getKey?_eq_some {β : Type v} {γ : Type w} [BEq α] [EquivBEq α] [Inhabited γ]
|
||
{f : (_ : α) → β → γ} {l : List ((_ : α) × β)} (hl : DistinctKeys l) {k k' : α}
|
||
(h : getKey? k l = some k') :
|
||
getValue! k (l.map fun p => ⟨p.1, f p.1 p.2⟩) = ((getValue? k l).map (f k')).get! := by
|
||
simp only [getValue!_eq_getValue?, getValue?_map_of_getKey?_eq_some hl h]
|
||
|
||
theorem getValueD_map {β : Type v} {γ : Type w} [BEq α] [EquivBEq α] {fallback : γ}
|
||
{f : (_ : α) → β → γ} {l : List ((_ : α) × β)} (hl : DistinctKeys l) {k : α} :
|
||
getValueD k (l.map fun p => ⟨p.1, f p.1 p.2⟩) fallback =
|
||
((getValue? k l).pmap (fun v h => f (getKey k l h) v)
|
||
(fun _ h => containsKey_eq_isSome_getValue?.trans (Option.isSome_of_mem h))).getD fallback := by
|
||
simp only [getValueD, getValue?_map hl]
|
||
|
||
theorem getValueD_map_of_getKey?_eq_some {β : Type v} {γ : Type w} [BEq α] [EquivBEq α]
|
||
{f : (_ : α) → β → γ} {l : List ((_ : α) × β)} (hl : DistinctKeys l) {k k' : α} {fallback : γ}
|
||
(h : getKey? k l = some k') :
|
||
getValueD k (l.map fun p => ⟨p.1, f p.1 p.2⟩) fallback = ((getValue? k l).map (f k')).getD fallback := by
|
||
simp only [getValueD_eq_getValue?, getValue?_map_of_getKey?_eq_some hl h]
|
||
|
||
theorem getKey?_filterMap [BEq α] [EquivBEq α] {β : Type v} {γ : Type w}
|
||
{f : (_ : α) → β → Option γ}
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l) :
|
||
getKey? k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))) =
|
||
(getKey? k l).pfilter (fun x h =>
|
||
(f x (getValue x l (containsKey_of_getKey?_eq_some h))).isSome) := by
|
||
simp only [getKey?_eq_getEntry?, getEntry?_filterMap hl, Option.map_bind,
|
||
Function.comp_def, Option.map_map, Option.pfilter_eq_pbind_ite,
|
||
Option.pbind_map, getValue, getValue?_eq_getEntry?]
|
||
rw [← Option.pbind_eq_bind]
|
||
congr; funext a h
|
||
simp only [getEntry?_congr (beq_of_getEntry?_eq_some h)]
|
||
simp only [show _ = _ from h, Option.map_some, Option.get_some]
|
||
cases f a.1 a.2 <;> rfl
|
||
|
||
theorem getKey!_filterMap [BEq α] [EquivBEq α] [Inhabited α] {β : Type v} {γ : Type w}
|
||
{f : (_ : α) → β → Option γ}
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l) :
|
||
getKey! k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))) =
|
||
((getKey? k l).pfilter (fun x h =>
|
||
(f x (getValue x l (containsKey_of_getKey?_eq_some h))).isSome)).get! := by
|
||
simp [getKey!_eq_getKey?, getKey?_filterMap hl]
|
||
|
||
theorem getKeyD_filterMap [BEq α] [EquivBEq α] {β : Type v} {γ : Type w}
|
||
{f : (_ : α) → β → Option γ}
|
||
{l : List ((_ : α) × β)} {k fallback: α} (hl : DistinctKeys l) :
|
||
getKeyD k (l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))) fallback =
|
||
((getKey? k l).pfilter (fun x h =>
|
||
(f x (getValue x l (containsKey_of_getKey?_eq_some h))).isSome)).getD fallback := by
|
||
simp [getKeyD_eq_getKey?, getKey?_filterMap hl]
|
||
|
||
theorem getValue_eq_get_getValue? [BEq α] {β : Type v} {a : α} {l : List ((_ : α) × β)}
|
||
{h : containsKey a l} :
|
||
getValue a l h = (getValue? a l).get (containsKey_eq_isSome_getValue? (a := a) ▸ h) := by
|
||
simp [getValue?_eq_some_getValue h]
|
||
|
||
theorem getKey?_filter [BEq α] [EquivBEq α] {β : Type v}
|
||
{f : (_ : α) → β → Bool}
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l) :
|
||
getKey? k (l.filter fun p => f p.1 p.2) =
|
||
(getKey? k l).pfilter (fun x h =>
|
||
f x (getValue x l (containsKey_of_getKey?_eq_some h))) := by
|
||
simp [getKey?_eq_getEntry?, getEntry?_filter hl, getValue_eq_get_getValue?,
|
||
getValue?_eq_getEntry?]
|
||
obtain (h|⟨p, h⟩) := Option.eq_none_or_eq_some (getEntry? k l)
|
||
· simp [h]
|
||
· simp [h, Option.filter_some, getEntry?_congr (beq_of_getEntry?_eq_some h)]
|
||
|
||
theorem getKey!_filter [BEq α] [EquivBEq α] [Inhabited α] {β : Type v}
|
||
{f : (_ : α) → β → Bool}
|
||
{l : List ((_ : α) × β)} {k : α} (hl : DistinctKeys l) :
|
||
getKey! k (l.filter fun p => f p.1 p.2) =
|
||
((getKey? k l).pfilter (fun x h =>
|
||
f x (getValue x l (containsKey_of_getKey?_eq_some h)))).get! := by
|
||
simp [getKey!_eq_getKey?, getKey?_filter hl]
|
||
|
||
theorem getKeyD_filter [BEq α] [EquivBEq α] {β : Type v}
|
||
{f : (_ : α) → β → Bool}
|
||
{l : List ((_ : α) × β)} {k fallback : α} (hl : DistinctKeys l) :
|
||
getKeyD k (l.filter fun p => f p.1 p.2) fallback =
|
||
((getKey? k l).pfilter (fun x h =>
|
||
f x (getValue x l (containsKey_of_getKey?_eq_some h)))).getD fallback := by
|
||
simp [getKeyD_eq_getKey?, getKey?_filter hl]
|
||
|
||
theorem length_filterMap_eq_length_iff {β : Type v} {γ : Type w} [BEq α] [EquivBEq α]
|
||
{f : (_ : α) → β → Option γ} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) :
|
||
(l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))).length = l.length ↔
|
||
∀ (a : α) (h : containsKey a l), (f (getKey a l h) (getValue a l h)).isSome := by
|
||
rw [List.filterMap_length_eq_length]
|
||
constructor
|
||
· intro h a ha
|
||
specialize h ⟨getKey a l ha, getValue a l ha⟩
|
||
simp only [Option.isSome_map] at h
|
||
apply h
|
||
apply getKey_getValue_mem
|
||
· intro h x hx
|
||
simp only [Option.isSome_map]
|
||
specialize h x.1 (containsKey_of_mem hx)
|
||
simp [getValue_of_mem hx distinct, getKey_of_mem hx distinct] at h
|
||
exact h
|
||
|
||
theorem length_filter_eq_length_iff {β : Type v} [BEq α] [EquivBEq α]
|
||
{f : (_ : α) → β → Bool} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) :
|
||
(l.filter fun p => (f p.1 p.2)).length = l.length ↔
|
||
∀ (a : α) (h : containsKey a l), (f (getKey a l h) (getValue a l h)) = true := by
|
||
simp [← List.filterMap_eq_filter, Option.guard,
|
||
forall_mem_iff_forall_contains_getKey_getValue (p := fun a b => f a b = true) distinct]
|
||
|
||
theorem length_filter_key_eq_length_iff {β : Type v} [BEq α] [EquivBEq α]
|
||
{f : (_ : α) → Bool} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) :
|
||
(l.filter fun p => f p.1).length = l.length ↔
|
||
∀ (a : α) (h : containsKey a l), f (getKey a l h) = true := by
|
||
simp [← List.filterMap_eq_filter,
|
||
forall_mem_iff_forall_contains_getKey_getValue (p := fun a b => f a = true) distinct]
|
||
|
||
theorem isEmpty_filterMap_eq_true [BEq α] [EquivBEq α] {β : Type v} {γ : Type w}
|
||
{f : (_ : α) → β → Option γ} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) :
|
||
(l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))).isEmpty = true ↔
|
||
∀ (k : α) (h : containsKey k l = true), f (getKey k l h) (getValue k l h) = none := by
|
||
simp only [List.isEmpty_iff, List.filterMap_eq_nil_iff, Option.map_eq_none_iff,
|
||
forall_mem_iff_forall_contains_getKey_getValue (p := fun a b => f a b = none) distinct]
|
||
|
||
theorem isEmpty_filterMap_eq_false [BEq α] [EquivBEq α] {β : Type v} {γ : Type w}
|
||
{f : (_ : α) → β → Option γ} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) :
|
||
(l.filterMap fun p => (f p.1 p.2).map (fun x => (⟨p.1, x⟩ : (_ : α) × γ))).isEmpty = false ↔
|
||
∃ (k : α) (h : containsKey k l = true), (f (getKey k l h) (getValue k l h)).isSome := by
|
||
rw [Bool.eq_false_iff, ne_eq, isEmpty_filterMap_eq_true distinct]
|
||
simp only [Classical.not_forall, Option.ne_none_iff_isSome]
|
||
|
||
theorem isEmpty_filter_eq_true [BEq α] [EquivBEq α] {β : Type v}
|
||
{f : (_ : α) → β → Bool} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) :
|
||
(l.filter fun p => (f p.1 p.2)).isEmpty = true ↔
|
||
∀ (k : α) (h : containsKey k l = true), f (getKey k l h) (getValue k l h) = false := by
|
||
simp only [List.isEmpty_iff, List.filter_eq_nil_iff, Bool.not_eq_true,
|
||
forall_mem_iff_forall_contains_getKey_getValue (p := fun a b => f a b = false) distinct]
|
||
|
||
theorem isEmpty_filter_eq_false [BEq α] [EquivBEq α] {β : Type v}
|
||
{f : (_ : α) → β → Bool} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) :
|
||
(l.filter fun p => (f p.1 p.2)).isEmpty = false ↔
|
||
∃ (k : α) (h : containsKey k l = true), f (getKey k l h) (getValue k l h) = true := by
|
||
rw [Bool.eq_false_iff, ne_eq, isEmpty_filter_eq_true distinct]
|
||
simp only [Classical.not_forall, Bool.not_eq_false]
|
||
|
||
theorem isEmpty_filter_key_eq_true [BEq α] [EquivBEq α] {β : Type v}
|
||
{f : (_ : α) → Bool} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) :
|
||
(l.filter fun p => (f p.1)).isEmpty = true ↔
|
||
∀ (k : α) (h : containsKey k l = true), f (getKey k l h) = false :=
|
||
isEmpty_filter_eq_true (f := fun a _ => f a) distinct
|
||
|
||
theorem isEmpty_filter_key_eq_false [BEq α] [EquivBEq α] {β : Type v}
|
||
{f : (_ : α) → Bool} {l : List ((_ : α) × β)} (distinct : DistinctKeys l) :
|
||
(l.filter fun p => (f p.1)).isEmpty = false ↔
|
||
∃ (k : α) (h : containsKey k l = true), f (getKey k l h) = true :=
|
||
isEmpty_filter_eq_false (f := fun a _ => f a) distinct
|
||
|
||
theorem toList_map' {β : Type v} {γ : Type w} {f : (_ : α) → β → γ} {l : List ((_ : α) × β)} :
|
||
l.map (fun p => (p.1, f p.1 p.2)) =
|
||
(l.map fun p => (⟨p.1, f p.1 p.2⟩ : (_ : α) × γ)).map (fun p => (p.1, p.2)) := by
|
||
simp
|
||
|
||
theorem toList_map {β : Type v} {γ : Type w} {f : (_ : α) → β → γ} {l : List ((_ : α) × β)} :
|
||
(l.map (fun p => (p.1, f p.1 p.2))).Perm
|
||
((l.map fun p => (⟨p.1, f p.1 p.2⟩ : (_ : α) × γ)).map (fun p => (p.1, p.2))) := by
|
||
simp [toList_map']
|
||
|
||
end Const
|
||
|
||
end FilterMap
|
||
|
||
section Min
|
||
|
||
private local instance leSigmaOfOrd [Ord α] : LE ((a : α) × β a) where
|
||
le a b := (compare a.1 b.1).isLE
|
||
|
||
private local instance [Ord α] : DecidableLE ((a : α) × β a) :=
|
||
fun a b => inferInstanceAs <| Decidable (compare a.1 b.1).isLE
|
||
|
||
private theorem leSigmaOfOrd_total [Ord α] [OrientedOrd α] (a b : (a : α) × β a) :
|
||
a ≤ b ∨ b ≤ a := by
|
||
simp only [leSigmaOfOrd]
|
||
rw [← OrientedCmp.isGE_iff_isLE]
|
||
cases compare b.fst a.fst <;> trivial
|
||
|
||
private local instance minSigmaOfOrd [Ord α] : Min ((a : α) × β a) where
|
||
min a b := if compare a.1 b.1 |>.isLE then a else b
|
||
|
||
private theorem min_def [Ord α] {p q : (a : α) × β a} :
|
||
min p q = if compare p.1 q.1 |>.isLE then p else q :=
|
||
rfl
|
||
|
||
private local instance [Ord α] [TransOrd α] :
|
||
Std.Associative (min : (a : α) × β a → (a : α) × β a → (a : α) × β a) where
|
||
assoc a b c := by
|
||
simp only [min_def]
|
||
split <;> split <;> (try split) <;> try rfl
|
||
· rename_i hab hac hbc
|
||
refine absurd ?_ hac
|
||
exact TransCmp.isLE_trans hab hbc
|
||
· rename_i hab hbc hac
|
||
refine absurd hac ?_
|
||
simp only [Bool.not_eq_true, Ordering.isLE_eq_false] at ⊢ hab hbc
|
||
exact TransCmp.gt_trans hab hbc
|
||
|
||
/-- Like `List.min?`, but using an `Ord` typeclass instead of a `Min` typeclass. -/
|
||
def minEntry? [Ord α] (xs : List ((a : α) × β a)) : Option ((a : α) × β a) :=
|
||
xs.min?
|
||
|
||
/-- Returns the smallest key in an associative list. -/
|
||
def minKey? [Ord α] (xs : List ((a : α) × β a)) : Option α :=
|
||
minEntry? xs |>.map Sigma.fst
|
||
|
||
theorem DistinctKeys.eq_of_mem_of_beq [BEq α] [EquivBEq α] {a b : (a : α) × β a}
|
||
{l : List ((a : α) × β a)} (hma : a ∈ l) (hmb : b ∈ l) (he : a.1 == b.1) (hd : DistinctKeys l) :
|
||
a = b := by
|
||
replace hd := hd.distinct
|
||
induction hma
|
||
· cases hmb
|
||
· rfl
|
||
· simp [pairwise_cons.mp hd |>.1 b.1 <| fst_mem_keys_of_mem ‹_›] at he
|
||
· rename_i _ ih
|
||
have hd := pairwise_cons.mp hd
|
||
cases hmb
|
||
· simp [BEq.symm_false <| hd.1 a.1 <| fst_mem_keys_of_mem ‹_›] at he
|
||
· exact ih ‹_› hd.2
|
||
|
||
private theorem min_eq_or [Ord α] {p q : (a : α) × β a} : min p q = p ∨ min p q = q := by
|
||
rw [min_def]
|
||
split <;> simp
|
||
|
||
private theorem min_eq_left [Ord α] {p q : (a : α) × β a} (h : compare p.1 q.1 |>.isLE) : min p q = p := by
|
||
simp [min_def, h]
|
||
|
||
private theorem min_eq_left_of_lt [Ord α] {p q : (a : α) × β a} (h : compare p.1 q.1 = .lt) : min p q = p :=
|
||
min_eq_left (Ordering.isLE_of_eq_lt h)
|
||
|
||
theorem minEntry?_eq_head? [Ord α] {l : List ((a : α) × β a)}
|
||
(hl : l.Pairwise (fun a b => compare a.1 b.1 = .lt)) : minEntry? l = l.head? := by
|
||
rw [minEntry?, List.min?_eq_head? (hl.imp min_eq_left_of_lt)]
|
||
|
||
@[simp]
|
||
theorem minEntry?_nil [Ord α] : minEntry? ([] : List ((a : α) × β a)) = none := by
|
||
simp [minEntry?, List.min?]
|
||
|
||
private theorem minEntry?_cons [Ord α] [TransOrd α] (e : (a : α) × β a) (l : List ((a : α) × β a)) :
|
||
minEntry? (e :: l) = some (match minEntry? l with
|
||
| none => e
|
||
| some w => min e w) := by
|
||
simp only [minEntry?, List.min?_cons]
|
||
split <;> simp_all only [List.min?_eq_none_iff, List.min?_nil, Option.elim_none, Option.elim_some]
|
||
|
||
theorem isSome_minEntry?_of_isEmpty_eq_false [Ord α] {l : List ((a : α) × β a)} (hl : l.isEmpty = false) :
|
||
(minEntry? l).isSome := by
|
||
cases l
|
||
· simp_all
|
||
· simp [minEntry?, List.min?]
|
||
|
||
private theorem le_min_iff [Ord α] [TransOrd α] {a b c : (a : α) × β a} :
|
||
a ≤ min b c ↔ a ≤ b ∧ a ≤ c := by
|
||
simp only [min_def]
|
||
split
|
||
· simp only [iff_self_and]
|
||
exact fun h => TransCmp.isLE_trans h ‹_›
|
||
· simp only [Bool.not_eq_true, Ordering.isLE_eq_false, OrientedCmp.gt_iff_lt, iff_and_self] at *
|
||
exact fun h => Ordering.isLE_of_eq_lt <| TransCmp.lt_of_isLE_of_lt h ‹_›
|
||
|
||
private theorem antisymm_subtype [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
Antisymm (α := Subtype (· ∈ l)) (· ≤ ·) where
|
||
antisymm a b hab hba := by
|
||
exact Subtype.ext
|
||
<| hd.eq_of_mem_of_beq a.property b.property
|
||
<| compare_eq_iff_beq.mp
|
||
<| OrientedCmp.isLE_antisymm hab hba
|
||
|
||
theorem minEntry?_eq_some_iff [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] (a : (a : α) × β a)
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
minEntry? l = some a ↔ a ∈ l ∧ ∀ b : α, containsKey b l → (compare a.fst b).isLE := by
|
||
haveI : LawfulOrderMin ((a : α) × β a) := .of_le_min_iff
|
||
(fun _ _ _ => le_min_iff) (fun _ _ => min_eq_or)
|
||
haveI : Refl (α := (a : α) × β a) (· ≤ ·) := ⟨fun _ => ReflCmp.isLE_rfl⟩
|
||
haveI : Antisymm (α := Subtype (· ∈ l)) (· ≤ ·) := antisymm_subtype hd
|
||
haveI : IsLinearOrder (Subtype (· ∈ l)) := IsLinearOrder.of_refl_of_antisymm_of_lawfulOrderMin
|
||
rw [minEntry?, List.min?_eq_some_iff_subtype]
|
||
simp only [and_congr_right_iff]
|
||
intro hm
|
||
apply Iff.intro
|
||
· intro h k hk
|
||
obtain ⟨e, hel, hek⟩ := containsKey_eq_true_iff_exists_mem.mp hk
|
||
exact TransCmp.isLE_trans (h _ hel) <| Ordering.isLE_of_eq_eq <| compare_eq_iff_beq.mpr hek
|
||
· intro h e he
|
||
exact h _ <| containsKey_of_mem he
|
||
|
||
theorem minKey?_eq_some_iff_getKey?_eq_self_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{k} {l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
minKey? l = some k ↔ getKey? k l = some k ∧ ∀ k' : α, containsKey k' l → (compare k k').isLE := by
|
||
simp only [minKey?, Option.map_eq_some_iff, minEntry?_eq_some_iff _ hd]
|
||
simp only [getKey?_eq_getEntry?, Option.map_eq_some_iff, getEntry?_eq_some_iff hd]
|
||
apply Iff.intro
|
||
· rintro ⟨_, ⟨hm, hcmp⟩, rfl⟩
|
||
exact ⟨⟨_, ⟨BEq.rfl, hm⟩, rfl⟩, hcmp⟩
|
||
· rintro ⟨⟨_, ⟨_, hm⟩, rfl⟩, hcmp⟩
|
||
exact ⟨_, ⟨hm, hcmp⟩, rfl⟩
|
||
|
||
theorem minKey?_eq_some_iff_mem_and_forall [Ord α] [LawfulEqOrd α] [TransOrd α] [BEq α]
|
||
[LawfulBEqOrd α] {k} {l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
minKey? l = some k ↔ containsKey k l ∧ ∀ k' : α, containsKey k' l → (compare k k').isLE := by
|
||
simp only [minKey?, Option.map_eq_some_iff, minEntry?_eq_some_iff _ hd]
|
||
apply Iff.intro
|
||
· rintro ⟨_, ⟨hm, hcmp⟩, rfl⟩
|
||
exact ⟨containsKey_of_mem hm, hcmp⟩
|
||
· rintro ⟨hc, hle⟩
|
||
have heq := beq_iff_eq.mp <| getKey_eq_getEntry_fst (α := α) ▸ getKey_beq hc
|
||
refine ⟨getEntry k l hc, ⟨getEntry_mem, ?_⟩, heq⟩
|
||
intro k' hk'
|
||
rw [heq]
|
||
exact hle _ hk'
|
||
|
||
theorem minEntry?_of_perm [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l l' : List ((a : α) × β a)} (hl : DistinctKeys l) (hp : l.Perm l') :
|
||
minEntry? l = minEntry? l' := by
|
||
cases l
|
||
case nil => simp_all only [List.nil_perm]
|
||
case cons e es =>
|
||
ext
|
||
simp only [minEntry?_eq_some_iff _ hl, hp.mem_iff, containsKey_of_perm hp]
|
||
exact minEntry?_eq_some_iff _ (hl.perm hp.symm) |>.symm
|
||
|
||
theorem minKey?_of_perm [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {l l' : List ((a : α) × β a)}
|
||
(hl : DistinctKeys l) (hp : l.Perm l') :
|
||
minKey? l = minKey? l' := by
|
||
simp only [minKey?, minEntry?_of_perm hl hp]
|
||
|
||
theorem minEntry?_eq_none_iff_isEmpty [Ord α] {l : List ((a : α) × β a)} :
|
||
minEntry? l = none ↔ l.isEmpty := by
|
||
simp only [List.isEmpty_iff, minEntry?, List.min?_eq_none_iff]
|
||
|
||
theorem minKey?_eq_none_iff_isEmpty [Ord α] {l : List ((a : α) × β a)} :
|
||
minKey? l = none ↔ l.isEmpty := by
|
||
simp [minKey?, minEntry?_eq_none_iff_isEmpty]
|
||
|
||
theorem minKey?_of_isEmpty [Ord α] [TransOrd α] {l : List ((a : α) × β a)} (he : l.isEmpty) :
|
||
minKey? l = none :=
|
||
minKey?_eq_none_iff_isEmpty.mpr he
|
||
|
||
theorem isNone_minEntry?_eq_isEmpty [Ord α] {l : List ((a : α) × β a)} :
|
||
(minEntry? l).isNone = l.isEmpty := by
|
||
rw [Bool.eq_iff_iff]
|
||
simp only [Option.isNone_iff_eq_none, minEntry?_eq_none_iff_isEmpty, List.isEmpty_iff]
|
||
|
||
theorem isNone_minKey?_eq_isEmpty [Ord α] {l : List ((a : α) × β a)} :
|
||
(minKey? l).isNone = l.isEmpty := by
|
||
simpa [minKey?] using isNone_minEntry?_eq_isEmpty
|
||
|
||
theorem isSome_minEntry?_eq_not_isEmpty [Ord α] {l : List ((a : α) × β a)} :
|
||
(minEntry? l).isSome = !l.isEmpty := by
|
||
rw [← Bool.not_inj_iff, Bool.not_not, Bool.eq_iff_iff, Bool.not_eq_true', Option.isSome_eq_false_iff,
|
||
Option.isNone_iff_eq_none]
|
||
apply minEntry?_eq_none_iff_isEmpty
|
||
|
||
theorem isSome_minKey?_eq_not_isEmpty [Ord α] {l : List ((a : α) × β a)} :
|
||
(minKey? l).isSome = !l.isEmpty := by
|
||
simpa [minKey?] using isSome_minEntry?_eq_not_isEmpty
|
||
|
||
theorem isSome_minKey?_iff_isEmpty_eq_false [Ord α] {l : List ((a : α) × β a)} :
|
||
(minKey? l).isSome ↔ l.isEmpty = false := by
|
||
simp [isSome_minKey?_eq_not_isEmpty]
|
||
|
||
private theorem min_apply [Ord α] {e₁ e₂ : (a : α) × β a} {f : (a : α) × β a → (a : α) × β a}
|
||
(hf : compare e₁.1 e₂.1 = compare (f e₁).1 (f e₂).1) :
|
||
min (f e₁) (f e₂) = f (min e₁ e₂) := by
|
||
simp only [min_def, hf, apply_ite f]
|
||
|
||
theorem minEntry?_map [Ord α] (l : List ((a : α) × β a)) (f : (a : α) × β a → (a : α) × β a)
|
||
(hf : ∀ e₁ e₂, compare e₁.1 e₂.1 = compare (f e₁).1 (f e₂).1) :
|
||
minEntry? (l.map f) = (minEntry? l).map f := by
|
||
simp only [minEntry?, List.min?]
|
||
cases l <;> try rfl
|
||
rename_i e es
|
||
simp only [List.map_cons, Option.map_some, Option.some.injEq]
|
||
rw [← List.foldr_reverse, ← List.foldr_reverse, ← List.map_reverse]
|
||
induction es.reverse with
|
||
| nil => rfl
|
||
| cons _ _ ih =>
|
||
simp [ih, min_apply (hf ..)]
|
||
|
||
theorem replaceEntry_eq_map [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k v}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
replaceEntry k v l = l.map fun e => if e.1 == k then ⟨k, v⟩ else e := by
|
||
induction l with
|
||
| nil => rfl
|
||
| cons e es ih =>
|
||
simp only [replaceEntry, cond_eq_ite, List.map_cons]
|
||
split
|
||
· rename_i heq
|
||
simp only [List.cons.injEq, true_and]
|
||
replace hl : containsKey k es = false := containsKey_congr heq ▸ hl.containsKey_eq_false
|
||
clear ih
|
||
induction es with
|
||
| nil => rfl
|
||
| cons e' es ih =>
|
||
simp only [List.map_cons, List.cons.injEq]
|
||
rw [containsKey_cons] at hl
|
||
simp only [Bool.or_eq_false_iff] at hl
|
||
simpa [hl.1] using ih hl.2
|
||
· simp [ih hl.tail]
|
||
|
||
theorem minEntry?_replaceEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α} {v : β k}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
minEntry? (replaceEntry k v l) =
|
||
(minEntry? l).map fun e => if e.1 == k then ⟨k, v⟩ else e := by
|
||
rw [replaceEntry_eq_map hl, minEntry?_map]
|
||
intro e₁ e₂
|
||
refine (TransCmp.congr_left ?_).trans (TransCmp.congr_right ?_)
|
||
all_goals
|
||
split
|
||
· exact compare_eq_iff_beq.mpr ‹_›
|
||
· exact compare_self
|
||
|
||
theorem isSome_minEntry?_of_contains [Ord α] [BEq α] {l : List ((a : α) × β a)} {b : α}
|
||
(hb : containsKey b l) :
|
||
(minEntry? l).isSome := by
|
||
apply isSome_minEntry?_of_isEmpty_eq_false
|
||
match l with
|
||
| [] => contradiction
|
||
| x :: xs => simp
|
||
|
||
theorem minEntry?_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α} {v : β k}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
minEntry? (insertEntry k v l) =
|
||
some (match minEntry? l with
|
||
| none => ⟨k, v⟩
|
||
| some w => if compare k w.fst |>.isLE then ⟨k, v⟩ else w) := by
|
||
simp only [insertEntry]
|
||
cases h : containsKey k l
|
||
· simp only [cond_false, minEntry?_cons, Option.some.injEq]
|
||
rfl
|
||
· rw [cond_true, minEntry?_replaceEntry hl, Option.map_eq_some_iff]
|
||
have := isSome_minEntry?_of_contains ‹_›
|
||
simp only [Option.isSome_iff_exists] at this
|
||
obtain ⟨a, ha⟩ := this
|
||
refine ⟨a, ha, ?_⟩
|
||
simp only [ha]
|
||
simp only [minEntry?_eq_some_iff _ hl] at ha
|
||
replace ha := ha.2 k ‹_›
|
||
cases hc : (compare k a.fst).isLE
|
||
· simp_all [OrientedCmp.gt_iff_lt, ← compare_eq_iff_beq]
|
||
· simp_all [OrientedCmp.isLE_antisymm ha hc, ← compare_eq_iff_beq]
|
||
|
||
theorem minKey?_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α} {v : β k}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
minKey? (insertEntry k v l) =
|
||
some ((minKey? l).elim k fun k' => if compare k k' |>.isLE then k else k') := by
|
||
simp only [minKey?, minEntry?_insertEntry hl]
|
||
cases minEntry? l <;> simp [apply_ite Sigma.fst]
|
||
|
||
theorem isSome_minEntry?_insert [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α} {v : β k}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
minEntry? (insertEntry k v l) |>.isSome := by
|
||
simp [minEntry?_insertEntry hl]
|
||
|
||
theorem isSome_minKey?_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α} {v : β k}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
minKey? (insertEntry k v l) |>.isSome := by
|
||
simp only [minKey?_insertEntry hl, Option.isSome_some]
|
||
|
||
theorem isSome_minEntry?_of_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k}
|
||
{l : List ((a : α) × β a)} (hc : containsKey k l) :
|
||
minEntry? l |>.isSome := by
|
||
simp [isSome_minEntry?_eq_not_isEmpty, isEmpty_eq_false_of_containsKey hc]
|
||
|
||
theorem isSome_minKey?_of_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k}
|
||
{l : List ((a : α) × β a)} (hc : containsKey k l) :
|
||
minKey? l |>.isSome := by
|
||
simpa [minKey?] using isSome_minEntry?_of_containsKey hc
|
||
|
||
theorem getEntry?_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {em} (hem : minEntry? l = some em) :
|
||
getEntry? em.1 l = some em := by
|
||
simp only [minEntry?_eq_some_iff _ hd] at hem
|
||
exact getEntry?_of_mem hd BEq.rfl hem.1
|
||
|
||
theorem minKey?_bind_getEntry? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
(minKey? l |>.bind fun k => getEntry? k l) = minEntry? l := by
|
||
rw [minKey?]
|
||
cases h : minEntry? l
|
||
· rfl
|
||
· simp [getEntry?_minKey? hd h]
|
||
|
||
theorem getKey?_minKey? [Ord α] [TransOrd α] [BEq α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {km} (hkm : minKey? l = some km) :
|
||
getKey? km l = some km := by
|
||
simp_all [minKey?_eq_some_iff_getKey?_eq_self_and_forall hd]
|
||
|
||
private theorem Option.get_eq_iff_eq_some {o : Option α} {h k} :
|
||
o.get h = k ↔ o = some k := by
|
||
simp [Option.eq_some_iff_get_eq, exists_prop_of_true h]
|
||
|
||
private theorem Option.eq_get_iff_some_eq {o : Option α} {h k} :
|
||
k = o.get h ↔ some k = o := by
|
||
conv => congr <;> rw [eq_comm]
|
||
exact get_eq_iff_eq_some
|
||
|
||
theorem getKey_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {km hc} :
|
||
(hkm : (minKey? l |>.get <| isSome_minKey?_of_containsKey hc) = km) → getKey km l hc = km := by
|
||
have := (Option.eq_some_iff_get_eq.mp <| getKey?_eq_some_getKey hc).2
|
||
simp only [← this, Option.get_eq_iff_eq_some]
|
||
exact getKey?_minKey? hd
|
||
|
||
theorem getKey!_minKey? [Ord α] [TransOrd α] [Inhabited α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {km} :
|
||
(hkm : minKey? l = some km) → getKey! km l = km := by
|
||
intro h
|
||
simp [getKey!_eq_getKey?, getKey?_minKey? hd h]
|
||
|
||
theorem getKeyD_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {km fallback} :
|
||
(hkm : minKey? l = some km) → getKeyD km l fallback = km := by
|
||
intro h
|
||
simp [getKeyD_eq_getKey?, getKey?_minKey? hd h]
|
||
|
||
theorem minKey?_bind_getKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
(minKey? l |>.bind fun k => getKey? k l) = minKey? l := by
|
||
cases h : minKey? l
|
||
· rfl
|
||
· simpa using getKey?_minKey? hd h
|
||
|
||
theorem containsKey_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {l : List ((a : α) × β a)}
|
||
(hd : DistinctKeys l) {km} (hkm : minKey? l = some km) :
|
||
containsKey km l := by
|
||
simp only [minKey?, Option.map_eq_some_iff, minEntry?_eq_some_iff _ hd] at hkm
|
||
obtain ⟨e, ⟨hm, _⟩, rfl⟩ := hkm
|
||
exact containsKey_of_mem hm
|
||
|
||
theorem minKey?_eraseKey_eq_iff_beq_minKey?_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{k} {l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
minKey? (eraseKey k l) = minKey? l ↔ ∀ {km}, minKey? l = some km → (k == km) = false := by
|
||
cases h : minKey? l
|
||
· simp_all [minKey?_eq_none_iff_isEmpty]
|
||
· simp only [minKey?_eq_some_iff_getKey?_eq_self_and_forall, getKey?_eraseKey,
|
||
containsKey_eraseKey, hd, hd.eraseKey] at ⊢ h
|
||
simp_all
|
||
|
||
theorem minKey?_eraseKey_eq_of_beq_minKey?_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{k} {l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(hc : ∀ {km}, minKey? l = some km → (k == km) = false) :
|
||
minKey? (eraseKey k l) = minKey? l := by
|
||
rw [minKey?_eraseKey_eq_iff_beq_minKey?_eq_false hd |>.mpr]
|
||
revert hc
|
||
cases minKey? l <;> simp
|
||
|
||
theorem minKey?_insertEntry_le_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α}
|
||
{v : β k} {l : List ((a : α) × β a)} (hl : DistinctKeys l) {km kmi} (hkm : minKey? l = some km)
|
||
(hkmi : (insertEntry k v l |> minKey? |>.get <| isSome_minKey?_insertEntry hl) = kmi) :
|
||
compare kmi km |>.isLE := by
|
||
simp only [← hkmi, minKey?_insertEntry hl, hkm, Option.get_some, Option.elim_some]
|
||
split <;> simp [*]
|
||
|
||
theorem minKey?_insertEntry_le_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α}
|
||
{v : β k} {l : List ((a : α) × β a)} (hl : DistinctKeys l) {kmi}
|
||
(hkmi : (insertEntry k v l |> minKey? |>.get <| isSome_minKey?_insertEntry hl) = kmi) :
|
||
compare kmi k |>.isLE := by
|
||
simp only [← hkmi, minKey?_insertEntry hl, Option.get_some]
|
||
cases minKey? l
|
||
· simp
|
||
· dsimp only [Option.elim_some]
|
||
cases hcmp : compare k _ <;> simp_all [OrientedCmp.gt_iff_lt]
|
||
|
||
theorem minKey?_le_of_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k km}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (hc : containsKey k l)
|
||
(hkm : (minKey? l |>.get <| isSome_minKey?_of_containsKey hc) = km) :
|
||
compare km k |>.isLE := by
|
||
simpa only [← hkm] using
|
||
minKey?_eq_some_iff_getKey?_eq_self_and_forall hd |>.mp (by simp) |>.2 _ hc
|
||
|
||
theorem le_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k} {l : List ((a : α) × β a)}
|
||
(hd : DistinctKeys l) :
|
||
(∀ k', minKey? l = some k' → (compare k k').isLE) ↔
|
||
(∀ k', containsKey k' l → (compare k k').isLE) := by
|
||
apply Iff.intro
|
||
· intro h k' hk'
|
||
have := isSome_minKey?_of_containsKey hk'
|
||
specialize h (minKey? l |>.get <| isSome_minKey?_of_containsKey hk') (by simp)
|
||
exact TransCmp.isLE_trans h <| minKey?_le_of_containsKey hd hk' rfl
|
||
· intro h k' hk'
|
||
exact h k' (containsKey_minKey? hd hk')
|
||
|
||
theorem isSome_minKey?_of_isSome_minKey?_eraseKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k}
|
||
{l : List ((a : α) × β a)} (hs : eraseKey k l |> minKey? |>.isSome) :
|
||
minKey? l |>.isSome := by
|
||
simp_all [isSome_minKey?_eq_not_isEmpty, isEmpty_eraseKey]
|
||
|
||
theorem containsKey_minKey?_eraseKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {kme}
|
||
(hkme : (eraseKey k l |> minKey?) = some kme) :
|
||
containsKey kme l := by
|
||
apply containsKey_of_containsKey_eraseKey hd
|
||
apply containsKey_minKey? hd.eraseKey hkme
|
||
|
||
theorem minKey?_le_minKey?_eraseKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k km kme}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(hkme : (eraseKey k l |> minKey?) = some kme)
|
||
(hkm : (minKey? l |>.get <|
|
||
isSome_minKey?_of_isSome_minKey?_eraseKey <| hkme ▸ Option.isSome_some) = km) :
|
||
compare km kme |>.isLE := by
|
||
apply minKey?_le_of_containsKey hd _ hkm
|
||
apply containsKey_minKey?_eraseKey hd hkme
|
||
|
||
theorem minKey?_cons [Ord α] [TransOrd α] (e : (a : α) × β a) (l : List ((a : α) × β a)) :
|
||
minKey? (e :: l) = some (match minKey? l with
|
||
| none => e.1
|
||
| some w => if compare e.1 w |>.isLE then e.1 else w) := by
|
||
simp [minKey?, minEntry?_cons]
|
||
cases minEntry? l
|
||
· rfl
|
||
· simp [min_def, apply_ite Sigma.fst]
|
||
|
||
theorem minEntry?_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α} {v : β k}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
minEntry? (insertEntryIfNew k v l) =
|
||
some (match minEntry? l with
|
||
| none => ⟨k, v⟩
|
||
| some e => if compare k e.1 = .lt then ⟨k, v⟩ else e) := by
|
||
simp [insertEntryIfNew]
|
||
cases hc : containsKey k l
|
||
· simp only [cond_false, minEntry?_cons, Option.some.injEq]
|
||
cases he : minEntry? l
|
||
· simp
|
||
· rename_i e
|
||
simp [min_def]
|
||
cases hcmp : compare k e.fst
|
||
· simp
|
||
· simp
|
||
rw [containsKey_congr <| compare_eq_iff_beq.mp hcmp] at hc
|
||
rw [containsKey_minKey? hd] at hc
|
||
· contradiction
|
||
· simp_all [minKey?]
|
||
· simp
|
||
· simp only [cond_true]
|
||
have := isSome_minEntry?_of_containsKey hc
|
||
cases h : minEntry? l
|
||
· simp_all
|
||
· simp only [Option.some.injEq]
|
||
split
|
||
· have := minKey?_le_of_containsKey hd hc (by simp [minKey?, h]; rfl)
|
||
simp_all [← OrientedCmp.gt_iff_lt]
|
||
· rfl
|
||
|
||
theorem minKey?_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α} {v : β k}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
minKey? (insertEntryIfNew k v l) =
|
||
some ((minKey? l).elim k fun k' => if compare k k' = .lt then k else k') := by
|
||
simp [minKey?, minEntry?_insertEntryIfNew hd]
|
||
cases minEntry? l <;> simp [apply_ite Sigma.fst]
|
||
|
||
theorem isSome_minEntry?_insertIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α} {v : β k}
|
||
{l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
minEntry? (insertEntryIfNew k v l) |>.isSome := by
|
||
simp [minEntry?_insertEntryIfNew hl]
|
||
|
||
theorem isSome_minKey?_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α}
|
||
{v : β k} {l : List ((a : α) × β a)} (hl : DistinctKeys l) :
|
||
minKey? (insertEntryIfNew k v l) |>.isSome := by
|
||
simp [minKey?_insertEntryIfNew hl]
|
||
|
||
theorem minKey?_insertEntryIfNew_le_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α}
|
||
{v : β k} {l : List ((a : α) × β a)} (hl : DistinctKeys l) {km kmi} (hkm : minKey? l = some km)
|
||
(hkmi : (insertEntryIfNew k v l |> minKey? |>.get <| isSome_minKey?_insertEntryIfNew hl) = kmi) :
|
||
compare kmi km |>.isLE := by
|
||
simp only [← hkmi, minKey?_insertEntryIfNew hl, hkm, Option.get_some, Option.elim_some]
|
||
split <;> simp [*]
|
||
|
||
theorem minKey?_insertEntryIfNew_le_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k kmi : α}
|
||
{v : β k} {l : List ((a : α) × β a)} (hl : DistinctKeys l)
|
||
(hkmi : (insertEntryIfNew k v l |> minKey? |>.get <| isSome_minKey?_insertEntryIfNew hl) = kmi) :
|
||
compare kmi k |>.isLE := by
|
||
simp only [← hkmi, minKey?_insertEntryIfNew hl, Option.get_some]
|
||
cases minKey? l
|
||
· simp
|
||
· simp only [Option.elim_some]
|
||
cases hcmp : compare k _ <;> (try simp; done)
|
||
all_goals
|
||
rw [OrientedCmp.eq_swap (cmp := compare)]
|
||
simp_all
|
||
|
||
theorem minKey?_eq_head?_keys [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (ho : l.Pairwise fun a b => compare a.1 b.1 = .lt) :
|
||
minKey? l = (keys l).head? := by
|
||
simp [minKey?, minEntry?_eq_head? ho, keys_eq_map]
|
||
|
||
theorem minKey?_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α] {k f}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
minKey? (modifyKey k f l) = minKey? l := by
|
||
cases hkm : minKey? l
|
||
· simp_all [minKey?_eq_none_iff_isEmpty, modifyKey]
|
||
· simp_all [minKey?_eq_some_iff_mem_and_forall, hd.modifyKey, containsKey_modifyKey]
|
||
|
||
theorem minKey?_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
{k f} {l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
minKey? (alterKey k f l) = some k ↔
|
||
(f (getValueCast? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k k').isLE := by
|
||
simp only [minKey?_eq_some_iff_getKey?_eq_self_and_forall hd.alterKey, getKey?_alterKey _ hd,
|
||
beq_self_eq_true, ↓reduceIte, ite_eq_left_iff, Bool.not_eq_true, Option.isSome_eq_false_iff,
|
||
Option.isNone_iff_eq_none, reduceCtorEq, imp_false, ← Option.isSome_iff_ne_none,
|
||
containsKey_alterKey hd, Bool.ite_eq_true_distrib, and_congr_right_iff]
|
||
intro hf
|
||
apply Iff.intro
|
||
· intro hk k' hk'
|
||
simpa [hk', hf] using hk k'
|
||
· intro hk k' hk'
|
||
simp only [hf, if_true_left] at hk'
|
||
by_cases hbeq : k == k'
|
||
· simp [compare_eq_iff_beq.mpr hbeq]
|
||
· exact hk k' (hk' hbeq)
|
||
|
||
namespace Const
|
||
|
||
variable {β : Type v}
|
||
|
||
theorem minKey?_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k f}
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) :
|
||
minKey? (modifyKey k f l) = (minKey? l).map fun km => if km == k then k else km := by
|
||
cases hkm : minKey? l
|
||
· simp_all [minKey?_eq_none_iff_isEmpty, modifyKey]
|
||
· simp_all [minKey?_eq_some_iff_getKey?_eq_self_and_forall, hd.constModifyKey, getKey?_modifyKey]
|
||
cases h : _ == k
|
||
· simp_all [BEq.symm_false h, containsKey_modifyKey]
|
||
· simp_all [containsKey_congr (BEq.symm h), containsKey_eq_isSome_getKey?,
|
||
getKey?_modifyKey]
|
||
intro k' hk'
|
||
cases hcmp : compare k k' <;> try rfl
|
||
replace hkm := hkm.2 k'
|
||
simp only [← compare_eq_iff_beq] at *
|
||
simp only [hcmp, reduceCtorEq, ↓reduceIte] at hk'
|
||
specialize hkm hk'
|
||
simp only [OrientedCmp.gt_iff_lt, Ordering.isLE_gt, Bool.false_eq_true] at *
|
||
have := TransCmp.lt_of_isLE_of_lt hkm hcmp
|
||
simp [this] at h
|
||
|
||
theorem minKey?_modifyKey_eq_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[LawfulEqOrd α] {k f} {l : List ((_ : α) × β)} (hd : DistinctKeys l) :
|
||
minKey? (modifyKey k f l) = minKey? l := by
|
||
simp only [minKey?_modifyKey hd]
|
||
cases minKey? l
|
||
· rfl
|
||
· simp only [beq_iff_eq, Option.map_some, Option.some.injEq, ite_eq_right_iff]
|
||
exact Eq.symm
|
||
|
||
theorem isSome_minKey?_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k f}
|
||
{l : List ((_ : α) × β)} :
|
||
(modifyKey k f l |> minKey?).isSome = !l.isEmpty := by
|
||
simp [isSome_minKey?_eq_not_isEmpty, isEmpty_modifyKey]
|
||
|
||
theorem isSome_minKey?_modifyKey_eq_isSome [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k f}
|
||
{l : List ((_ : α) × β)} :
|
||
(modifyKey k f l |> minKey?).isSome = (minKey? l).isSome := by
|
||
simp [isSome_minKey?_eq_not_isEmpty, isEmpty_modifyKey]
|
||
|
||
theorem minKey?_modifyKey_beq [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k f km kmm}
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) (hkm : minKey? l = some km)
|
||
(hkmm : (modifyKey k f l |> minKey? |>.get <|
|
||
isSome_minKey?_modifyKey_eq_isSome.trans <| hkm ▸ Option.isSome_some) = kmm) :
|
||
kmm == km := by
|
||
simp only [minKey?_modifyKey hd, Option.get_map] at hkmm
|
||
simp only [Option.eq_some_iff_get_eq] at hkm
|
||
simp only [← hkmm, ← hkm.2]
|
||
split
|
||
· exact BEq.symm ‹_›
|
||
· exact BEq.rfl
|
||
|
||
theorem minKey?_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{k f} {l : List ((_ : α) × β)} (hd : DistinctKeys l) :
|
||
minKey? (alterKey k f l) = some k ↔
|
||
(f (getValue? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k k').isLE := by
|
||
simp only [minKey?_eq_some_iff_getKey?_eq_self_and_forall hd.constAlterKey, getKey?_alterKey _ hd,
|
||
← compare_eq_iff_beq, compare_self, ↓reduceIte, ite_eq_left_iff, Bool.not_eq_true,
|
||
Option.isSome_eq_false_iff, Option.isNone_iff_eq_none, reduceCtorEq, imp_false,
|
||
← Option.isSome_iff_ne_none, containsKey_alterKey hd, Bool.ite_eq_true_distrib,
|
||
and_congr_right_iff]
|
||
intro hf
|
||
apply Iff.intro
|
||
· intro hk k' hk'
|
||
simpa [hk', hf] using hk k'
|
||
· intro hk k' hk'
|
||
simp only [hf, if_true_left] at hk'
|
||
by_cases heq : compare k k' = .eq
|
||
· simp [heq]
|
||
· exact hk k' (hk' heq)
|
||
|
||
end Const
|
||
|
||
/-- Given a proof that the list is nonempty, returns the smallest key in an associative list. -/
|
||
def minKey [Ord α] (xs : List ((a : α) × β a)) (h : xs.isEmpty = false) : α :=
|
||
minKey? xs |>.get (by simp [isSome_minKey?_eq_not_isEmpty, h])
|
||
|
||
theorem minKey_of_perm [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {l l' : List ((a : α) × β a)}
|
||
{hl} (hd : DistinctKeys l) (hp : l.Perm l') :
|
||
minKey l hl = minKey l' (hp.isEmpty_eq ▸ hl) := by
|
||
simp [minKey, minKey?_of_perm hd hp]
|
||
|
||
theorem minKey_eq_get_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} {he} :
|
||
minKey l he = (minKey? l |>.get (by simp [isSome_minKey?_eq_not_isEmpty, he])) :=
|
||
(rfl)
|
||
|
||
theorem minKey?_eq_some_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} {he} :
|
||
minKey? l = some (minKey l he) := by
|
||
simp [minKey_eq_get_minKey?]
|
||
|
||
theorem minKey_eq_iff_getKey?_eq_self_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he km} :
|
||
minKey l he = km ↔ getKey? km l = some km ∧ ∀ k, containsKey k l → (compare km k).isLE := by
|
||
simp [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some,
|
||
minKey?_eq_some_iff_getKey?_eq_self_and_forall hd]
|
||
|
||
theorem minKey_eq_iff_mem_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[LawfulEqOrd α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {he km} :
|
||
minKey l he = km ↔ containsKey km l ∧ ∀ k, containsKey k l → (compare km k).isLE := by
|
||
simp [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, minKey?_eq_some_iff_mem_and_forall hd]
|
||
|
||
theorem minKey_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {l : List ((a : α) × β a)}
|
||
(hd : DistinctKeys l) {k v} :
|
||
(insertEntry k v l |> minKey <| isEmpty_insertEntry) =
|
||
((minKey? l).elim k fun k' => if compare k k' |>.isLE then k else k') := by
|
||
simp [minKey_eq_get_minKey?, minKey?_insertEntry hd]
|
||
|
||
theorem minKey_insertEntry_le_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v he} :
|
||
compare (insertEntry k v l |> minKey <| isEmpty_insertEntry) (minKey l he) |>.isLE := by
|
||
simp only [minKey_eq_get_minKey?]
|
||
exact minKey?_insertEntry_le_minKey? hd (by simp) rfl
|
||
|
||
theorem minKey_insertEntry_le_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
compare (insertEntry k v l |> minKey <| isEmpty_insertEntry) k |>.isLE := by
|
||
simp only [minKey_eq_get_minKey?]
|
||
exact minKey?_insertEntry_le_self hd rfl
|
||
|
||
theorem containsKey_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
containsKey (minKey l he) l :=
|
||
containsKey_minKey? hd minKey?_eq_some_minKey
|
||
|
||
theorem minKey_le_of_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k} (hc : containsKey k l) :
|
||
compare (minKey l <| isEmpty_eq_false_iff_exists_containsKey.mpr ⟨k, hc⟩) k |>.isLE :=
|
||
minKey?_le_of_containsKey hd hc minKey_eq_get_minKey?.symm
|
||
|
||
theorem le_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k he} :
|
||
(compare k (minKey l he)).isLE ↔ (∀ k', containsKey k' l → (compare k k').isLE) := by
|
||
simp only [minKey_eq_get_minKey?, ← le_minKey? hd, Option.eq_some_iff_get_eq]
|
||
simp only [exists_prop_of_true (isSome_minKey?_iff_isEmpty_eq_false.mpr he), forall_eq']
|
||
|
||
theorem getKey?_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
getKey? (minKey l he) l = some (minKey l he) :=
|
||
getKey?_minKey? hd minKey?_eq_some_minKey
|
||
|
||
theorem getKey_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
getKey (minKey l he) l (containsKey_minKey hd) = minKey l he := by
|
||
simpa [getKey?_eq_some_getKey (containsKey_minKey hd)] using getKey?_minKey hd (he := he)
|
||
|
||
theorem getKey!_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
getKey! (minKey l he) l = minKey l he := by
|
||
simpa [getKey_eq_getKey!] using getKey_minKey hd
|
||
|
||
theorem getKeyD_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he fallback} :
|
||
getKeyD (minKey l he) l fallback = minKey l he := by
|
||
simpa [getKey_eq_getKeyD (fallback := fallback)] using getKey_minKey hd
|
||
|
||
theorem minKey_eraseKey_eq_iff_beq_minKey_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k he} :
|
||
(eraseKey k l |> minKey <| he) =
|
||
minKey l (isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he) ↔
|
||
(k == (minKey l <| isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he)) = false := by
|
||
simp only [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, Option.some_get]
|
||
constructor
|
||
· intro h
|
||
exact minKey?_eraseKey_eq_iff_beq_minKey?_eq_false hd |>.mp h (by rw [Option.some_get])
|
||
· intro h
|
||
apply minKey?_eraseKey_eq_iff_beq_minKey?_eq_false hd |>.mpr
|
||
intro km hkm
|
||
simp_all only [Option.get_some]
|
||
|
||
theorem minKey_eraseKey_eq_of_beq_minKey_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k he} :
|
||
(hc : (k == (minKey l (isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he))) = false) →
|
||
(eraseKey k l |> minKey <| he) =
|
||
minKey l (isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he) :=
|
||
minKey_eraseKey_eq_iff_beq_minKey_eq_false hd |>.mpr
|
||
|
||
theorem minKey_le_minKey_erase [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k he} :
|
||
compare (minKey l <| isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he)
|
||
(eraseKey k l |> minKey <| he) |>.isLE :=
|
||
minKey?_le_minKey?_eraseKey hd minKey?_eq_some_minKey minKey_eq_get_minKey?.symm
|
||
|
||
theorem minKey_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
(insertEntryIfNew k v l |> minKey <| isEmpty_insertEntryIfNew) =
|
||
(minKey? l).elim k fun k' => if compare k k' = .lt then k else k' := by
|
||
simp [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, ← minKey?_insertEntryIfNew hd (v := v)]
|
||
|
||
theorem minKey_insertEntryIfNew_le_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v he} :
|
||
compare (insertEntryIfNew k v l |> minKey <| isEmpty_insertEntryIfNew)
|
||
(minKey l he) |>.isLE :=
|
||
minKey?_insertEntryIfNew_le_minKey? hd minKey?_eq_some_minKey minKey_eq_get_minKey?.symm
|
||
|
||
theorem minKey_insertEntryIfNew_le_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
compare (insertEntryIfNew k v l |> minKey <| isEmpty_insertEntryIfNew) k |>.isLE :=
|
||
minKey?_insertEntryIfNew_le_self hd minKey_eq_get_minKey?.symm
|
||
|
||
theorem minKey_eq_head_keys [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (ho : l.Pairwise fun a b => compare a.1 b.1 = .lt) {he} :
|
||
minKey l he = (keys l).head (by simp_all [keys_eq_map, List.isEmpty_eq_false_iff]) := by
|
||
simp [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, ← List.head?_eq_some_head,
|
||
minKey?_eq_head?_keys ho]
|
||
|
||
theorem minKey_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α] {k f}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
(modifyKey k f l |> minKey <| he) = minKey l (isEmpty_modifyKey k f l ▸ he) := by
|
||
simp [minKey_eq_get_minKey?, minKey?_modifyKey hd]
|
||
|
||
theorem minKey_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k f he} :
|
||
(alterKey k f l |> minKey <| he) = k ↔
|
||
(f (getValueCast? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k k').isLE := by
|
||
simp [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, minKey?_alterKey_eq_self hd]
|
||
|
||
namespace Const
|
||
|
||
variable {β : Type v}
|
||
|
||
theorem minKey_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f he} :
|
||
(modifyKey k f l |> minKey <| he) =
|
||
if (minKey l <| isEmpty_modifyKey k f l ▸ he) == k then
|
||
k
|
||
else
|
||
(minKey l <| isEmpty_modifyKey k f l ▸ he) := by
|
||
simp [minKey_eq_get_minKey?, minKey?_modifyKey hd, Option.get_map]
|
||
|
||
theorem minKey_modifyKey_eq_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f he} :
|
||
(modifyKey k f l |> minKey <| he) = minKey l (isEmpty_modifyKey k f l ▸ he) := by
|
||
simp [minKey_eq_get_minKey?, minKey?_modifyKey_eq_minKey? hd]
|
||
|
||
theorem minKey_modifyKey_beq [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f he} :
|
||
(modifyKey k f l |> minKey <| he) == (minKey l <| isEmpty_modifyKey k f l ▸ he) :=
|
||
minKey?_modifyKey_beq hd minKey?_eq_some_minKey rfl
|
||
|
||
theorem minKey_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f he} :
|
||
(alterKey k f l |> minKey <| he) = k ↔
|
||
(f (getValue? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k k').isLE := by
|
||
simp [minKey_eq_get_minKey?, Option.get_eq_iff_eq_some, minKey?_alterKey_eq_self hd]
|
||
|
||
end Const
|
||
|
||
/-- Returns the smallest key in an associative list or panics if the list is empty. -/
|
||
@[expose] def minKey! [Ord α] [Inhabited α] (xs : List ((a : α) × β a)) : α :=
|
||
minKey? xs |>.get!
|
||
|
||
theorem minKey!_of_perm [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l l' : List ((a : α) × β a)} (hd : DistinctKeys l) (hp : l.Perm l') :
|
||
minKey! l = minKey! l' := by
|
||
simp [minKey!, minKey?_of_perm hd hp]
|
||
|
||
theorem minKey!_eq_get!_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} :
|
||
minKey! l = (minKey? l).get! :=
|
||
rfl
|
||
|
||
theorem minKey_eq_minKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} {he} :
|
||
minKey l he = minKey! l := by
|
||
simp [minKey_eq_get_minKey?, minKey!_eq_get!_minKey?, Option.get_eq_get!]
|
||
|
||
theorem minKey?_eq_some_minKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (he : l.isEmpty = false) :
|
||
minKey? l = some (minKey! l) := by
|
||
simp [← minKey_eq_minKey! (he := he), minKey_eq_get_minKey?]
|
||
|
||
theorem minKey!_eq_default [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (h : l.isEmpty) :
|
||
minKey! l = default := by
|
||
simp [minKey!, minKey?_eq_none_iff_isEmpty.mpr h]
|
||
|
||
theorem minKey!_eq_iff_getKey?_eq_self_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {km} :
|
||
minKey! l = km ↔ getKey? km l = some km ∧ ∀ k, containsKey k l → (compare km k).isLE := by
|
||
simpa [minKey_eq_minKey!] using minKey_eq_iff_getKey?_eq_self_and_forall hd (he := he)
|
||
|
||
theorem minKey!_eq_iff_mem_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[LawfulEqOrd α] [Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(he : l.isEmpty = false) {km} :
|
||
minKey! l = km ↔ containsKey km l ∧ ∀ k, containsKey k l → (compare km k).isLE := by
|
||
simpa [minKey_eq_minKey!] using minKey_eq_iff_mem_and_forall hd (he := he)
|
||
|
||
theorem minKey!_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
(insertEntry k v l |> minKey!) =
|
||
((minKey? l).elim k fun k' => if compare k k' |>.isLE then k else k') := by
|
||
simpa [minKey_eq_minKey!] using minKey_insertEntry hd
|
||
|
||
theorem minKey!_insertEntry_le_minKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {k v} :
|
||
compare (insertEntry k v l |> minKey!) (minKey! l) |>.isLE := by
|
||
simpa [minKey_eq_minKey!] using minKey_insertEntry_le_minKey hd (he := he)
|
||
|
||
theorem minKey!_insertEntry_le_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
compare (insertEntry k v l |> minKey!) k |>.isLE := by
|
||
simpa [minKey_eq_minKey!] using minKey_insertEntry_le_self hd
|
||
|
||
theorem containsKey_minKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) :
|
||
containsKey (minKey! l) l := by
|
||
simpa [minKey_eq_minKey!] using containsKey_minKey hd (he := he)
|
||
|
||
theorem minKey!_le_of_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k} (hc : containsKey k l) :
|
||
compare (minKey! l) k |>.isLE := by
|
||
simpa [minKey_eq_minKey!] using minKey_le_of_containsKey hd hc
|
||
|
||
theorem le_minKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {k} :
|
||
(compare k (minKey! l)).isLE ↔ (∀ k', containsKey k' l → (compare k k').isLE) := by
|
||
simpa [minKey_eq_minKey!] using le_minKey hd (he := he)
|
||
|
||
theorem getKey?_minKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) :
|
||
getKey? (minKey! l) l = some (minKey! l) := by
|
||
simpa [minKey_eq_minKey!] using getKey?_minKey hd (he := he)
|
||
|
||
theorem getKey_minKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
getKey (minKey! l) l he = minKey! l := by
|
||
simpa [minKey_eq_minKey!] using getKey_minKey hd (he := isEmpty_eq_false_of_containsKey he)
|
||
|
||
theorem getKey_minKey!_eq_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
getKey (minKey! l) l he = minKey l (isEmpty_eq_false_of_containsKey he) := by
|
||
simpa [minKey_eq_minKey!] using getKey_minKey hd (he := isEmpty_eq_false_of_containsKey he)
|
||
|
||
theorem getKey!_minKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) :
|
||
getKey! (minKey! l) l = minKey! l := by
|
||
simpa [minKey_eq_minKey!] using getKey!_minKey hd (he := he)
|
||
|
||
theorem getKeyD_minKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {fallback} :
|
||
getKeyD (minKey! l) l fallback = minKey! l := by
|
||
simpa [minKey_eq_minKey!] using getKeyD_minKey hd (he := he)
|
||
|
||
theorem minKey!_eraseKey_eq_iff_beq_minKey_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k}
|
||
(he : (eraseKey k l).isEmpty = false) :
|
||
(eraseKey k l |> minKey!) = minKey! l ↔ (k == (minKey! l)) = false := by
|
||
simpa [minKey_eq_minKey!] using minKey_eraseKey_eq_iff_beq_minKey_eq_false hd (he := he)
|
||
|
||
theorem minKey!_eraseKey_eq_iff_beq_minKey!_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k}
|
||
(he : (eraseKey k l).isEmpty = false) :
|
||
(eraseKey k l |> minKey!) = minKey! l ↔ (k == (minKey! l)) = false := by
|
||
simpa [minKey_eq_minKey!] using minKey_eraseKey_eq_iff_beq_minKey_eq_false hd (he := he)
|
||
|
||
theorem minKey!_eraseKey_eq_of_beq_minKey!_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k}
|
||
(he : (eraseKey k l).isEmpty = false) : (heq : (k == minKey! l) = false) →
|
||
(eraseKey k l |> minKey!) = minKey! l := by
|
||
simpa only [minKey_eq_minKey!] using minKey_eraseKey_eq_of_beq_minKey_eq_false hd (he := he)
|
||
|
||
theorem minKey!_le_minKey!_erase [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k} (he : (eraseKey k l).isEmpty = false) :
|
||
compare (minKey! l) (eraseKey k l |> minKey!) |>.isLE := by
|
||
simpa only [minKey_eq_minKey!] using minKey_le_minKey_erase hd (he := he)
|
||
|
||
theorem minKey!_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
(insertEntryIfNew k v l |> minKey!) =
|
||
(minKey? l).elim k fun k' => if compare k k' = .lt then k else k' := by
|
||
simpa only [minKey_eq_minKey!] using minKey_insertEntryIfNew hd
|
||
|
||
theorem minKey!_insertEntryIfNew_le_minKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {k v} :
|
||
compare (insertEntryIfNew k v l |> minKey!) (minKey! l) |>.isLE := by
|
||
simpa only [minKey_eq_minKey!] using minKey_insertEntryIfNew_le_minKey hd (he := he)
|
||
|
||
theorem minKey!_insertEntryIfNew_le_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
compare (insertEntryIfNew k v l |> minKey!) k |>.isLE := by
|
||
simpa only [minKey_eq_minKey!] using minKey_insertEntryIfNew_le_self hd
|
||
|
||
theorem minKey!_eq_head!_keys [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (ho : l.Pairwise fun a b => compare a.1 b.1 = .lt) :
|
||
minKey! l = (keys l).head! := by
|
||
cases l
|
||
· rfl
|
||
· simp only [minKey!_eq_get!_minKey?, minKey?_eq_head?_keys ho]
|
||
rfl
|
||
|
||
theorem minKey!_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k f} :
|
||
(modifyKey k f l |> minKey!) = minKey! l := by
|
||
cases he : l.isEmpty
|
||
· have := minKey_modifyKey hd (he := isEmpty_modifyKey k f l ▸ he)
|
||
-- fails after inlining `this`
|
||
simpa [minKey_eq_minKey!] using this
|
||
· simp_all [modifyKey]
|
||
|
||
theorem minKey!_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k f}
|
||
(he : (alterKey k f l).isEmpty = false) :
|
||
(alterKey k f l |> minKey!) = k ↔
|
||
(f (getValueCast? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k k').isLE := by
|
||
simpa only [minKey_eq_minKey!] using minKey_alterKey_eq_self hd (he := he)
|
||
|
||
namespace Const
|
||
|
||
variable {β : Type v}
|
||
|
||
theorem minKey!_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f} (he : (modifyKey k f l).isEmpty = false) :
|
||
(modifyKey k f l |> minKey!) = if (minKey! l) == k then k else (minKey! l) := by
|
||
simpa only [minKey_eq_minKey!] using minKey_modifyKey hd (he := he)
|
||
|
||
theorem minKey!_modifyKey_eq_minKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
[Inhabited α] {l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f} :
|
||
(modifyKey k f l |> minKey!) = minKey! l := by
|
||
cases he : l.isEmpty
|
||
· have := minKey_modifyKey_eq_minKey hd (he := isEmpty_modifyKey k f l ▸ he)
|
||
-- fails after inlining `this`
|
||
simpa [minKey_eq_minKey!] using this
|
||
· simp_all [modifyKey]
|
||
|
||
theorem minKey!_modifyKey_beq [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f} :
|
||
(modifyKey k f l |> minKey!) == (minKey! l) := by
|
||
cases he : l.isEmpty
|
||
· have := minKey_modifyKey_beq hd (he := isEmpty_modifyKey k f l ▸ he)
|
||
-- fails after inlining `this`
|
||
simpa [minKey_eq_minKey!] using this
|
||
· simp_all [modifyKey]
|
||
|
||
theorem minKey!_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f} (he : (alterKey k f l).isEmpty = false) :
|
||
(alterKey k f l |> minKey!) = k ↔
|
||
(f (getValue? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k k').isLE := by
|
||
simpa only [minKey_eq_minKey!] using minKey_alterKey_eq_self hd (he := he)
|
||
|
||
end Const
|
||
|
||
/-- Returns the smallest key in an associative list or `fallback` if the list is empty. -/
|
||
def minKeyD [Ord α] (xs : List ((a : α) × β a)) (fallback : α) : α :=
|
||
minKey? xs |>.getD fallback
|
||
|
||
theorem minKeyD_of_perm [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l l' : List ((a : α) × β a)} {fallback} (hd : DistinctKeys l) (hp : l.Perm l') :
|
||
minKeyD l fallback = minKeyD l' fallback := by
|
||
simp [minKeyD, minKey?_of_perm hd hp]
|
||
|
||
theorem minKeyD_eq_getD_minKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} {fallback} :
|
||
minKeyD l fallback = (minKey? l).getD fallback :=
|
||
(rfl)
|
||
|
||
theorem minKey_eq_minKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} {he fallback} :
|
||
minKey l he = minKeyD l fallback := by
|
||
simp [minKey_eq_get_minKey?, minKeyD_eq_getD_minKey?, Option.get_eq_getD (fallback := fallback)]
|
||
|
||
theorem minKey?_eq_some_minKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} {fallback} (he : l.isEmpty = false) :
|
||
minKey? l = some (minKeyD l fallback) := by
|
||
simp [← minKey_eq_minKeyD (he := he), minKey_eq_get_minKey?]
|
||
|
||
theorem minKey!_eq_minKeyD_default [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} :
|
||
minKey! l = minKeyD l default := by
|
||
simp [minKey!_eq_get!_minKey?, minKeyD_eq_getD_minKey?, Option.get!_eq_getD]
|
||
|
||
theorem minKeyD_eq_fallback [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} {fallback} (h : l.isEmpty) :
|
||
minKeyD l fallback = fallback := by
|
||
simp [minKeyD, minKey?_eq_none_iff_isEmpty.mpr h]
|
||
|
||
theorem minKeyD_eq_iff_getKey?_eq_self_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {km fallback} :
|
||
minKeyD l fallback = km ↔
|
||
getKey? km l = some km ∧ ∀ k, containsKey k l → (compare km k).isLE := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using
|
||
minKey_eq_iff_getKey?_eq_self_and_forall hd (he := he)
|
||
|
||
theorem minKeyD_eq_iff_mem_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[LawfulEqOrd α] {l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(he : l.isEmpty = false) {km fallback} :
|
||
minKeyD l fallback = km ↔ containsKey km l ∧ ∀ k, containsKey k l → (compare km k).isLE := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using
|
||
minKey_eq_iff_mem_and_forall hd (he := he)
|
||
|
||
theorem minKeyD_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v fallback} :
|
||
(insertEntry k v l |> minKeyD <| fallback) =
|
||
((minKey? l).elim k fun k' => if compare k k' |>.isLE then k else k') := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using minKey_insertEntry hd
|
||
|
||
theorem minKeyD_insertEntry_le_minKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {k v fallback} :
|
||
compare (insertEntry k v l |> minKeyD <| fallback) (minKeyD l fallback) |>.isLE := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using minKey_insertEntry_le_minKey hd (he := he)
|
||
|
||
theorem minKeyD_insertEntry_le_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v fallback} :
|
||
compare (insertEntry k v l |> minKeyD <| fallback) k |>.isLE := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using minKey_insertEntry_le_self hd
|
||
|
||
theorem containsKey_minKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {fallback} :
|
||
containsKey (minKeyD l fallback) l := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using containsKey_minKey hd (he := he)
|
||
|
||
theorem minKeyD_le_of_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k} (hc : containsKey k l) {fallback} :
|
||
compare (minKeyD l fallback) k |>.isLE := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using minKey_le_of_containsKey hd hc
|
||
|
||
theorem le_minKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {k fallback} :
|
||
(compare k (minKeyD l fallback)).isLE ↔ (∀ k', containsKey k' l → (compare k k').isLE) := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using le_minKey hd (he := he)
|
||
|
||
theorem getKey?_minKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {fallback} :
|
||
getKey? (minKeyD l fallback) l = some (minKeyD l fallback) := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using getKey?_minKey hd (he := he)
|
||
|
||
theorem getKey_minKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {fallback he} :
|
||
getKey (minKeyD l fallback) l he = minKeyD l fallback := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using
|
||
getKey_minKey hd (he := isEmpty_eq_false_of_containsKey he)
|
||
|
||
theorem getKey_minKeyD_eq_minKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {fallback he} :
|
||
getKey (minKeyD l fallback) l he = minKey l (isEmpty_eq_false_of_containsKey he) := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using
|
||
getKey_minKey hd (he := isEmpty_eq_false_of_containsKey he)
|
||
|
||
theorem getKey!_minKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {fallback} :
|
||
getKey! (minKeyD l fallback) l = minKeyD l fallback := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using getKey!_minKey hd (he := he)
|
||
|
||
theorem getKeyD_minKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {fallback fallback'} :
|
||
getKeyD (minKeyD l fallback) l fallback' = minKeyD l fallback := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using getKeyD_minKey hd (he := he)
|
||
|
||
theorem minKeyD_eraseKey_eq_iff_beq_minKey_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k fallback}
|
||
(he : (eraseKey k l).isEmpty = false) :
|
||
(eraseKey k l |> minKeyD <| fallback) = minKeyD l fallback ↔
|
||
(k == (minKeyD l fallback)) = false := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using
|
||
minKey_eraseKey_eq_iff_beq_minKey_eq_false hd (he := he)
|
||
|
||
theorem minKeyD_eraseKey_eq_iff_beq_minKeyD_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k fallback}
|
||
(he : (eraseKey k l).isEmpty = false) :
|
||
(eraseKey k l |> minKeyD <| fallback) = minKeyD l fallback ↔
|
||
(k == (minKeyD l fallback)) = false := by
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using
|
||
minKey_eraseKey_eq_iff_beq_minKey_eq_false hd (he := he)
|
||
|
||
theorem minKeyD_eraseKey_eq_of_beq_minKeyD_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k fallback}
|
||
(he : (eraseKey k l).isEmpty = false) : (heq : (k == minKeyD l fallback) = false) →
|
||
(eraseKey k l |> minKeyD <| fallback) = minKeyD l fallback:= by
|
||
simpa only [minKey_eq_minKeyD (fallback := fallback)] using
|
||
minKey_eraseKey_eq_of_beq_minKey_eq_false hd (he := he)
|
||
|
||
theorem minKeyD_le_minKeyD_erase [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k} (he : (eraseKey k l).isEmpty = false)
|
||
{fallback} :
|
||
compare (minKeyD l fallback) (eraseKey k l |> minKeyD <| fallback) |>.isLE := by
|
||
simpa only [minKey_eq_minKeyD (fallback := fallback)] using
|
||
minKey_le_minKey_erase hd (he := he)
|
||
|
||
theorem minKeyD_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v fallback} :
|
||
(insertEntryIfNew k v l |> minKeyD <| fallback) =
|
||
(minKey? l).elim k fun k' => if compare k k' = .lt then k else k' := by
|
||
simpa only [minKey_eq_minKeyD (fallback := fallback)] using minKey_insertEntryIfNew hd
|
||
|
||
theorem minKeyD_insertEntryIfNew_le_minKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {k v fallback} :
|
||
compare (insertEntryIfNew k v l |> minKeyD <| fallback) (minKeyD l fallback) |>.isLE := by
|
||
simpa only [minKey_eq_minKeyD (fallback := fallback)] using
|
||
minKey_insertEntryIfNew_le_minKey hd (he := he)
|
||
|
||
theorem minKeyD_insertEntryIfNew_le_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v fallback} :
|
||
compare (insertEntryIfNew k v l |> minKeyD <| fallback) k |>.isLE := by
|
||
simpa only [minKey_eq_minKeyD (fallback := fallback)] using minKey_insertEntryIfNew_le_self hd
|
||
|
||
theorem minKeyD_eq_headD_keys [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (ho : l.Pairwise fun a b => compare a.1 b.1 = .lt) {fallback} :
|
||
minKeyD l fallback = (keys l).headD fallback := by
|
||
simp [minKeyD_eq_getD_minKey?, minKey?_eq_head?_keys ho]
|
||
|
||
theorem minKeyD_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k f fallback} :
|
||
(modifyKey k f l |> minKeyD <| fallback) = minKeyD l fallback := by
|
||
cases he : l.isEmpty
|
||
· have := minKey_modifyKey hd (he := isEmpty_modifyKey k f l ▸ he)
|
||
-- fails after inlining `this`
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using this
|
||
· simp_all [modifyKey]
|
||
|
||
theorem minKeyD_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k f fallback}
|
||
(he : (alterKey k f l).isEmpty = false) :
|
||
(alterKey k f l |> minKeyD <| fallback) = k ↔
|
||
(f (getValueCast? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k k').isLE := by
|
||
simpa only [minKey_eq_minKeyD (fallback := fallback)] using minKey_alterKey_eq_self hd (he := he)
|
||
|
||
namespace Const
|
||
|
||
variable {β : Type v}
|
||
|
||
theorem minKeyD_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f} (he : (modifyKey k f l).isEmpty = false)
|
||
{fallback} :
|
||
(modifyKey k f l |> minKeyD <| fallback) = if (minKeyD l fallback) == k then k else (minKeyD l fallback) := by
|
||
simpa only [minKey_eq_minKeyD (fallback := fallback)] using minKey_modifyKey hd (he := he)
|
||
|
||
theorem minKeyD_modifyKey_eq_minKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f fallback} :
|
||
(modifyKey k f l |> minKeyD <| fallback) = minKeyD l fallback := by
|
||
cases he : l.isEmpty
|
||
· have := minKey_modifyKey_eq_minKey hd (he := isEmpty_modifyKey k f l ▸ he)
|
||
-- fails after inlining `this`
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using this
|
||
· simp_all [modifyKey]
|
||
|
||
theorem minKeyD_modifyKey_beq [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f fallback} :
|
||
(modifyKey k f l |> minKeyD <| fallback) == (minKeyD l fallback) := by
|
||
cases he : l.isEmpty
|
||
· have := minKey_modifyKey_beq hd (he := isEmpty_modifyKey k f l ▸ he)
|
||
-- fails after inlining `this`
|
||
simpa [minKey_eq_minKeyD (fallback := fallback)] using this
|
||
· simp_all [modifyKey]
|
||
|
||
theorem minKeyD_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f} (he : (alterKey k f l).isEmpty = false)
|
||
{fallback} :
|
||
(alterKey k f l |> minKeyD <| fallback) = k ↔
|
||
(f (getValue? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k k').isLE := by
|
||
simpa only [minKey_eq_minKeyD (fallback := fallback)] using minKey_alterKey_eq_self hd (he := he)
|
||
|
||
end Const
|
||
|
||
end Min
|
||
|
||
section Max
|
||
|
||
/-- Returns the largest key in an associative list. -/
|
||
abbrev maxKey? [Ord α] (xs : List ((a : α) × β a)) : Option α :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey? xs
|
||
|
||
theorem maxKey?_eq_some_iff_getKey?_eq_self_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{k} {l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
maxKey? l = some k ↔ getKey? k l = some k ∧ ∀ k' : α, containsKey k' l → (compare k' k).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_eq_some_iff_getKey?_eq_self_and_forall hd
|
||
|
||
theorem maxKey?_eq_some_iff_mem_and_forall [Ord α] [LawfulEqOrd α] [TransOrd α] [BEq α]
|
||
[LawfulBEqOrd α] {k} {l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
maxKey? l = some k ↔ containsKey k l ∧ ∀ k' : α, containsKey k' l → (compare k' k).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_eq_some_iff_mem_and_forall hd
|
||
|
||
theorem maxKey?_of_perm [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {l l' : List ((a : α) × β a)}
|
||
(hl : DistinctKeys l) (hp : l.Perm l') :
|
||
maxKey? l = maxKey? l' :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_of_perm hl hp
|
||
|
||
theorem maxKey?_eq_none_iff_isEmpty [Ord α] {l : List ((a : α) × β a)} :
|
||
maxKey? l = none ↔ l.isEmpty :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_eq_none_iff_isEmpty
|
||
|
||
theorem maxKey?_of_isEmpty [Ord α] [TransOrd α] {l : List ((a : α) × β a)} (he : l.isEmpty) :
|
||
maxKey? l = none :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_of_isEmpty he
|
||
|
||
theorem isNone_maxKey?_eq_isEmpty [Ord α] {l : List ((a : α) × β a)} :
|
||
(maxKey? l).isNone = l.isEmpty :=
|
||
letI : Ord α := .opposite inferInstance
|
||
isNone_minKey?_eq_isEmpty
|
||
|
||
theorem isSome_maxKey?_eq_not_isEmpty [Ord α] {l : List ((a : α) × β a)} :
|
||
(maxKey? l).isSome = !l.isEmpty :=
|
||
letI : Ord α := .opposite inferInstance
|
||
isSome_minKey?_eq_not_isEmpty
|
||
|
||
theorem isSome_maxKey?_iff_isEmpty_eq_false [Ord α] {l : List ((a : α) × β a)} :
|
||
(maxKey? l).isSome ↔ l.isEmpty = false :=
|
||
letI : Ord α := .opposite inferInstance
|
||
isSome_minKey?_iff_isEmpty_eq_false
|
||
|
||
theorem maxKey?_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α} {v : β k}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
maxKey? (insertEntry k v l) =
|
||
some ((maxKey? l).elim k fun k' => if compare k' k |>.isLE then k else k') :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_insertEntry hd
|
||
|
||
theorem isSome_maxKey?_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α} {v : β k}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
maxKey? (insertEntry k v l) |>.isSome :=
|
||
letI : Ord α := .opposite inferInstance
|
||
isSome_minKey?_insertEntry hd
|
||
|
||
theorem isSome_maxKey?_of_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k}
|
||
{l : List ((a : α) × β a)} (hc : containsKey k l) :
|
||
maxKey? l |>.isSome :=
|
||
letI : Ord α := .opposite inferInstance
|
||
isSome_minKey?_of_containsKey hc
|
||
|
||
theorem getKey?_maxKey? [Ord α] [TransOrd α] [BEq α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {km} (hkm : maxKey? l = some km) :
|
||
getKey? km l = some km :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey?_minKey? hd hkm
|
||
|
||
theorem getKey_maxKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {km hc} :
|
||
(hkm : (maxKey? l |>.get <| isSome_maxKey?_of_containsKey hc) = km) → getKey km l hc = km :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey_minKey? hd
|
||
|
||
theorem getKey!_maxKey? [Ord α] [TransOrd α] [Inhabited α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {km} :
|
||
(hkm : maxKey? l = some km) → getKey! km l = km :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey!_minKey? hd
|
||
|
||
theorem getKeyD_maxKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {km fallback} :
|
||
(hkm : maxKey? l = some km) → getKeyD km l fallback = km :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKeyD_minKey? hd
|
||
|
||
theorem maxKey?_bind_getKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
(maxKey? l |>.bind fun k => getKey? k l) = maxKey? l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_bind_getKey? hd
|
||
|
||
theorem containsKey_maxKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {l : List ((a : α) × β a)}
|
||
(hd : DistinctKeys l) {km} (hkm : maxKey? l = some km) :
|
||
containsKey km l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
containsKey_minKey? hd hkm
|
||
|
||
theorem maxKey?_eraseKey_eq_iff_beq_maxKey?_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{k} {l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
maxKey? (eraseKey k l) = maxKey? l ↔ ∀ {km}, maxKey? l = some km → (k == km) = false :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_eraseKey_eq_iff_beq_minKey?_eq_false hd
|
||
|
||
theorem maxKey?_eraseKey_eq_of_beq_maxKey?_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{k} {l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(hc : ∀ {km}, maxKey? l = some km → (k == km) = false) :
|
||
maxKey? (eraseKey k l) = maxKey? l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_eraseKey_eq_of_beq_minKey?_eq_false hd hc
|
||
|
||
theorem maxKey?_le_maxKey?_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α}
|
||
{v : β k} {l : List ((a : α) × β a)} (hd : DistinctKeys l) {km kmi} (hkm : maxKey? l = some km)
|
||
(hkmi : (insertEntry k v l |> maxKey? |>.get <| isSome_maxKey?_insertEntry hd) = kmi) :
|
||
compare km kmi |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_insertEntry_le_minKey? hd hkm hkmi
|
||
|
||
theorem self_le_maxKey?_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α}
|
||
{v : β k} {l : List ((a : α) × β a)} (hd : DistinctKeys l) {kmi}
|
||
(hkmi : (insertEntry k v l |> maxKey? |>.get <| isSome_maxKey?_insertEntry hd) = kmi) :
|
||
compare k kmi |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_insertEntry_le_self hd hkmi
|
||
|
||
theorem maxKey?_le_of_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k km}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (hc : containsKey k l)
|
||
(hkm : (maxKey? l |>.get <| isSome_maxKey?_of_containsKey hc) = km) :
|
||
compare k km |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
(minKey?_le_of_containsKey hd hc hkm :)
|
||
|
||
theorem maxKey?_le [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k} {l : List ((a : α) × β a)}
|
||
(hd : DistinctKeys l) :
|
||
(∀ k', maxKey? l = some k' → (compare k' k).isLE) ↔
|
||
(∀ k', containsKey k' l → (compare k' k).isLE) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
le_minKey? hd
|
||
|
||
theorem isSome_maxKey?_of_isSome_maxKey?_eraseKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k}
|
||
{l : List ((a : α) × β a)} (hs : eraseKey k l |> maxKey? |>.isSome) :
|
||
maxKey? l |>.isSome :=
|
||
letI : Ord α := .opposite inferInstance
|
||
isSome_minKey?_of_isSome_minKey?_eraseKey hs
|
||
|
||
theorem containsKey_maxKey?_eraseKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {kme}
|
||
(hkme : (eraseKey k l |> maxKey?) = some kme) :
|
||
containsKey kme l := by
|
||
apply containsKey_of_containsKey_eraseKey hd
|
||
apply containsKey_maxKey? hd.eraseKey hkme
|
||
|
||
theorem maxKey?_eraseKey_le_maxKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k km kme}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(hkme : (eraseKey k l |> maxKey?) = some kme)
|
||
(hkm : (maxKey? l |>.get <|
|
||
isSome_maxKey?_of_isSome_maxKey?_eraseKey <| hkme ▸ Option.isSome_some) = km) :
|
||
compare kme km |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
(minKey?_le_minKey?_eraseKey hd hkme hkm :)
|
||
|
||
theorem maxKey?_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α} {v : β k}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
maxKey? (insertEntryIfNew k v l) =
|
||
some ((maxKey? l).elim k fun k' => if compare k' k = .lt then k else k') :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_insertEntryIfNew hd
|
||
|
||
theorem isSome_maxKey?_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α}
|
||
{v : β k} {l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
maxKey? (insertEntryIfNew k v l) |>.isSome :=
|
||
letI : Ord α := .opposite inferInstance
|
||
isSome_minKey?_insertEntryIfNew hd
|
||
|
||
theorem maxKey?_le_maxKey?_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k : α}
|
||
{v : β k} {l : List ((a : α) × β a)} (hd : DistinctKeys l) {km kmi} (hkm : maxKey? l = some km)
|
||
(hkmi : (insertEntryIfNew k v l |> maxKey? |>.get <| isSome_maxKey?_insertEntryIfNew hd) = kmi) :
|
||
compare km kmi |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_insertEntryIfNew_le_minKey? hd hkm hkmi
|
||
|
||
theorem self_le_maxKey?_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k kmi : α}
|
||
{v : β k} {l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(hkmi : (insertEntryIfNew k v l |> maxKey? |>.get <| isSome_maxKey?_insertEntryIfNew hd) = kmi) :
|
||
compare k kmi |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
(minKey?_insertEntryIfNew_le_self hd hkmi :)
|
||
|
||
theorem reverse_keys {l : List ((a : α) × β a)} :
|
||
(keys l).reverse = keys l.reverse := by
|
||
simp [keys_eq_map]
|
||
|
||
theorem maxKey?_eq_getLast?_keys [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(ho : l.Pairwise fun a b => compare a.1 b.1 = .lt) :
|
||
maxKey? l = (keys l).getLast? := by
|
||
rw [← List.head?_reverse, reverse_keys, maxKey?_of_perm hd (List.reverse_perm l).symm]
|
||
letI : Ord α := .opposite inferInstance
|
||
exact minKey?_eq_head?_keys (List.pairwise_reverse.mpr ho)
|
||
|
||
theorem maxKey?_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α] {k f}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
maxKey? (modifyKey k f l) = maxKey? l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_modifyKey hd
|
||
|
||
theorem maxKey?_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
{k f} {l : List ((a : α) × β a)} (hd : DistinctKeys l) :
|
||
maxKey? (alterKey k f l) = some k ↔
|
||
(f (getValueCast? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k' k).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_alterKey_eq_self hd
|
||
|
||
namespace Const
|
||
|
||
variable {β : Type v}
|
||
|
||
theorem maxKey?_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k f}
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) :
|
||
maxKey? (modifyKey k f l) = (maxKey? l).map fun km => if km == k then k else km :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_modifyKey hd
|
||
|
||
theorem maxKey?_modifyKey_eq_maxKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[LawfulEqOrd α] {k f} {l : List ((_ : α) × β)} (hd : DistinctKeys l) :
|
||
maxKey? (modifyKey k f l) = maxKey? l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_modifyKey_eq_minKey? hd
|
||
|
||
theorem isSome_maxKey?_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k f}
|
||
{l : List ((_ : α) × β)} :
|
||
(modifyKey k f l |> maxKey?).isSome = !l.isEmpty :=
|
||
letI : Ord α := .opposite inferInstance
|
||
isSome_minKey?_modifyKey
|
||
|
||
theorem isSome_maxKey?_modifyKey_eq_isSome [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k f}
|
||
{l : List ((_ : α) × β)} :
|
||
(modifyKey k f l |> maxKey?).isSome = (maxKey? l).isSome :=
|
||
letI : Ord α := .opposite inferInstance
|
||
isSome_minKey?_modifyKey_eq_isSome
|
||
|
||
theorem maxKey?_modifyKey_beq [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {k f km kmm}
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) (hkm : maxKey? l = some km)
|
||
(hkmm : (modifyKey k f l |> maxKey? |>.get <|
|
||
isSome_maxKey?_modifyKey_eq_isSome.trans <| hkm ▸ Option.isSome_some) = kmm) :
|
||
kmm == km :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_modifyKey_beq hd hkm hkmm
|
||
|
||
theorem maxKey?_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{k f} {l : List ((_ : α) × β)} (hd : DistinctKeys l) :
|
||
maxKey? (alterKey k f l) = some k ↔
|
||
(f (getValue? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k' k).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_alterKey_eq_self hd
|
||
|
||
end Const
|
||
|
||
/-- Given a proof that the list is nonempty, returns the largest key in an associative list. -/
|
||
abbrev maxKey [Ord α] (xs : List ((a : α) × β a)) (h : xs.isEmpty = false) : α :=
|
||
letI : Ord α := .opposite inferInstance; minKey xs h
|
||
|
||
theorem maxKey_of_perm [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {l l' : List ((a : α) × β a)}
|
||
{hl} (hd : DistinctKeys l) (hp : l.Perm l') :
|
||
maxKey l hl = maxKey l' (hp.isEmpty_eq ▸ hl) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_of_perm hd hp
|
||
|
||
theorem maxKey_eq_get_maxKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} {he} :
|
||
maxKey l he = (maxKey? l |>.get (by simp [isSome_maxKey?_eq_not_isEmpty, he])) :=
|
||
(rfl)
|
||
|
||
theorem maxKey?_eq_some_maxKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} {he} :
|
||
maxKey? l = some (maxKey l he) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_eq_some_minKey
|
||
|
||
theorem maxKey_eq_iff_getKey?_eq_self_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he km} :
|
||
maxKey l he = km ↔ getKey? km l = some km ∧ ∀ k, containsKey k l → (compare k km).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_eq_iff_getKey?_eq_self_and_forall hd
|
||
|
||
theorem maxKey_eq_iff_mem_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[LawfulEqOrd α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {he km} :
|
||
maxKey l he = km ↔ containsKey km l ∧ ∀ k, containsKey k l → (compare k km).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_eq_iff_mem_and_forall hd
|
||
|
||
theorem maxKey_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] {l : List ((a : α) × β a)}
|
||
(hd : DistinctKeys l) {k v} :
|
||
(insertEntry k v l |> maxKey <| isEmpty_insertEntry) =
|
||
((maxKey? l).elim k fun k' => if compare k' k |>.isLE then k else k') :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_insertEntry hd
|
||
|
||
theorem maxKey_le_maxKey_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v he} :
|
||
compare (maxKey l he) (insertEntry k v l |> maxKey <| isEmpty_insertEntry) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_insertEntry_le_minKey hd
|
||
|
||
theorem self_le_maxKey_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
compare k (insertEntry k v l |> maxKey <| isEmpty_insertEntry) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_insertEntry_le_self hd
|
||
|
||
theorem containsKey_maxKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
containsKey (maxKey l he) l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
containsKey_minKey hd
|
||
|
||
theorem le_maxKey_of_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k} (hc : containsKey k l) :
|
||
compare k (maxKey l <| isEmpty_eq_false_iff_exists_containsKey.mpr ⟨k, hc⟩) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_le_of_containsKey hd hc
|
||
|
||
theorem maxKey_le [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k he} :
|
||
(compare (maxKey l he) k).isLE ↔ (∀ k', containsKey k' l → (compare k' k).isLE) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
le_minKey hd
|
||
|
||
theorem getKey?_maxKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
getKey? (maxKey l he) l = some (maxKey l he) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey?_minKey hd
|
||
|
||
theorem getKey_maxKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
getKey (maxKey l he) l (containsKey_maxKey hd) = maxKey l he :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey_minKey hd
|
||
|
||
theorem getKey!_maxKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
getKey! (maxKey l he) l = maxKey l he :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey!_minKey hd
|
||
|
||
theorem getKeyD_maxKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he fallback} :
|
||
getKeyD (maxKey l he) l fallback = maxKey l he :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKeyD_minKey hd
|
||
|
||
theorem maxKey_eraseKey_eq_iff_beq_maxKey_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k he} :
|
||
(eraseKey k l |> maxKey <| he) =
|
||
maxKey l (isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he) ↔
|
||
(k == (maxKey l <| isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he)) = false :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_eraseKey_eq_iff_beq_minKey_eq_false hd
|
||
|
||
theorem maxKey_eraseKey_eq_of_beq_maxKey_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k he} :
|
||
(hc : (k == (maxKey l (isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he))) = false) →
|
||
(eraseKey k l |> maxKey <| he) =
|
||
maxKey l (isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_eraseKey_eq_of_beq_minKey_eq_false hd
|
||
|
||
theorem maxKey_eraseKey_le_maxKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k he} :
|
||
compare (eraseKey k l |> maxKey <| he)
|
||
(maxKey l <| isEmpty_eq_false_of_isEmpty_eraseKey_eq_false hd he) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_le_minKey_erase hd
|
||
|
||
theorem maxKey_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
(insertEntryIfNew k v l |> maxKey <| isEmpty_insertEntryIfNew) =
|
||
(maxKey? l).elim k fun k' => if compare k' k = .lt then k else k' :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_insertEntryIfNew hd
|
||
|
||
theorem maxKey_le_maxKey_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v he} :
|
||
compare (maxKey l he)
|
||
(insertEntryIfNew k v l |> maxKey <| isEmpty_insertEntryIfNew) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_insertEntryIfNew_le_minKey hd
|
||
|
||
theorem self_le_maxKey_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
compare k (insertEntryIfNew k v l |> maxKey <| isEmpty_insertEntryIfNew) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_insertEntryIfNew_le_self hd
|
||
|
||
theorem maxKey_eq_getLast_keys [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(ho : l.Pairwise fun a b => compare a.1 b.1 = .lt) {he} :
|
||
maxKey l he = (keys l).getLast (by simp_all [keys_eq_map, List.isEmpty_eq_false_iff]) := by
|
||
simp only [List.getLast_eq_head_reverse, reverse_keys, maxKey_of_perm hd (List.reverse_perm l).symm]
|
||
letI : Ord α := .opposite inferInstance
|
||
exact minKey_eq_head_keys (List.pairwise_reverse.mpr ho)
|
||
|
||
theorem maxKey_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α] {k f}
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
(modifyKey k f l |> maxKey <| he) = maxKey l (isEmpty_modifyKey k f l ▸ he) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_modifyKey hd
|
||
|
||
theorem maxKey_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k f he} :
|
||
(alterKey k f l |> maxKey <| he) = k ↔
|
||
(f (getValueCast? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k' k).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_alterKey_eq_self hd
|
||
|
||
namespace Const
|
||
|
||
variable {β : Type v}
|
||
|
||
theorem maxKey_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f he} :
|
||
(modifyKey k f l |> maxKey <| he) =
|
||
if (maxKey l <| isEmpty_modifyKey k f l ▸ he) == k then
|
||
k
|
||
else
|
||
(maxKey l <| isEmpty_modifyKey k f l ▸ he) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_modifyKey hd
|
||
|
||
theorem maxKey_modifyKey_eq_maxKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f he} :
|
||
(modifyKey k f l |> maxKey <| he) = maxKey l (isEmpty_modifyKey k f l ▸ he) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_modifyKey_eq_minKey hd
|
||
|
||
theorem maxKey_modifyKey_beq [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f he} :
|
||
(modifyKey k f l |> maxKey <| he) == (maxKey l <| isEmpty_modifyKey k f l ▸ he) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_modifyKey_beq hd
|
||
|
||
theorem maxKey_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f he} :
|
||
(alterKey k f l |> maxKey <| he) = k ↔
|
||
(f (getValue? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k' k).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_alterKey_eq_self hd
|
||
|
||
end Const
|
||
|
||
/-- Given a proof that the list is nonempty, returns the smallest key in an associative list. -/
|
||
def maxKey! [Ord α] [Inhabited α] (xs : List ((a : α) × β a)) : α :=
|
||
maxKey? xs |>.get!
|
||
|
||
theorem maxKey!_of_perm [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l l' : List ((a : α) × β a)} (hd : DistinctKeys l) (hp : l.Perm l') :
|
||
maxKey! l = maxKey! l' :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_of_perm hd hp
|
||
|
||
theorem maxKey!_eq_get!_maxKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} :
|
||
maxKey! l = (maxKey? l).get! :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_eq_get!_minKey?
|
||
|
||
theorem maxKey_eq_maxKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} {he} :
|
||
maxKey l he = maxKey! l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_eq_minKey!
|
||
|
||
theorem maxKey?_eq_some_maxKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (he : l.isEmpty = false) :
|
||
maxKey? l = some (maxKey! l) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_eq_some_minKey! he
|
||
|
||
theorem maxKey!_eq_default [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (h : l.isEmpty) :
|
||
maxKey! l = default :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_eq_default h
|
||
|
||
theorem maxKey!_eq_iff_getKey?_eq_self_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {km} :
|
||
maxKey! l = km ↔ getKey? km l = some km ∧ ∀ k, containsKey k l → (compare k km).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_eq_iff_getKey?_eq_self_and_forall hd he
|
||
|
||
theorem maxKey!_eq_iff_mem_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[LawfulEqOrd α] [Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(he : l.isEmpty = false) {km} :
|
||
maxKey! l = km ↔ containsKey km l ∧ ∀ k, containsKey k l → (compare k km).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_eq_iff_mem_and_forall hd he
|
||
|
||
theorem maxKey!_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
(insertEntry k v l |> maxKey!) =
|
||
((maxKey? l).elim k fun k' => if compare k' k |>.isLE then k else k') :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_insertEntry hd
|
||
|
||
theorem maxKey!_le_maxKey!_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {k v} :
|
||
compare (maxKey! l) (insertEntry k v l |> maxKey!) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_insertEntry_le_minKey! hd he
|
||
|
||
theorem self_le_maxKey!_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
compare k (insertEntry k v l |> maxKey!) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_insertEntry_le_self hd
|
||
|
||
theorem containsKey_maxKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) :
|
||
containsKey (maxKey! l) l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
containsKey_minKey! hd he
|
||
|
||
theorem le_maxKey!_of_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k} (hc : containsKey k l) :
|
||
compare k (maxKey! l) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_le_of_containsKey hd hc
|
||
|
||
theorem maxKey!_le [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {k} :
|
||
(compare (maxKey! l) k).isLE ↔ (∀ k', containsKey k' l → (compare k' k).isLE) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
le_minKey! hd he
|
||
|
||
theorem getKey?_maxKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) :
|
||
getKey? (maxKey! l) l = some (maxKey! l) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey?_minKey! hd he
|
||
|
||
theorem getKey_maxKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
getKey (maxKey! l) l he = maxKey! l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey_minKey! hd
|
||
|
||
theorem getKey_maxKey!_eq_maxKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {he} :
|
||
getKey (maxKey! l) l he = maxKey l (isEmpty_eq_false_of_containsKey he) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey_minKey!_eq_minKey hd
|
||
|
||
theorem getKey!_maxKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) :
|
||
getKey! (maxKey! l) l = maxKey! l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey!_minKey! hd he
|
||
|
||
theorem getKeyD_maxKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {fallback} :
|
||
getKeyD (maxKey! l) l fallback = maxKey! l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKeyD_minKey! hd he
|
||
|
||
theorem maxKey!_eraseKey_eq_iff_beq_maxKey_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k}
|
||
(he : (eraseKey k l).isEmpty = false) :
|
||
(eraseKey k l |> maxKey!) = maxKey! l ↔ (k == (maxKey! l)) = false :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_eraseKey_eq_iff_beq_minKey_eq_false hd he
|
||
|
||
theorem maxKey!_eraseKey_eq_iff_beq_maxKey!_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k}
|
||
(he : (eraseKey k l).isEmpty = false) :
|
||
(eraseKey k l |> maxKey!) = maxKey! l ↔ (k == (maxKey! l)) = false :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_eraseKey_eq_iff_beq_minKey!_eq_false hd he
|
||
|
||
theorem maxKey!_eraseKey_eq_of_beq_maxKey!_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k}
|
||
(he : (eraseKey k l).isEmpty = false) : (heq : (k == maxKey! l) = false) →
|
||
(eraseKey k l |> maxKey!) = maxKey! l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_eraseKey_eq_of_beq_minKey!_eq_false hd he
|
||
|
||
theorem maxKey!_erase_le_maxKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k} (he : (eraseKey k l).isEmpty = false) :
|
||
compare (eraseKey k l |> maxKey!) (maxKey! l) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_le_minKey!_erase hd he
|
||
|
||
theorem maxKey!_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
(insertEntryIfNew k v l |> maxKey!) =
|
||
(maxKey? l).elim k fun k' => if compare k' k = .lt then k else k' :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_insertEntryIfNew hd
|
||
|
||
theorem maxKey!_le_maxKey!_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {k v} :
|
||
compare (maxKey! l) (insertEntryIfNew k v l |> maxKey!) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_insertEntryIfNew_le_minKey! hd he
|
||
|
||
theorem self_le_maxKey!_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v} :
|
||
compare k (insertEntryIfNew k v l |> maxKey!) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_insertEntryIfNew_le_self hd
|
||
|
||
theorem maxKey!_eq_getLast!_keys [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(ho : l.Pairwise fun a b => compare a.1 b.1 = .lt) :
|
||
maxKey! l = (keys l).getLast! := by
|
||
simp only [List.getLast!_eq_getLast?_getD, maxKey!_eq_get!_maxKey?,
|
||
Option.get!_eq_getD, maxKey?_eq_getLast?_keys hd ho]
|
||
|
||
theorem maxKey!_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k f} :
|
||
(modifyKey k f l |> maxKey!) = maxKey! l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_modifyKey hd
|
||
|
||
theorem maxKey!_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
[Inhabited α] {l : List ((a : α) × β a)} (hd : DistinctKeys l) {k f}
|
||
(he : (alterKey k f l).isEmpty = false) :
|
||
(alterKey k f l |> maxKey!) = k ↔
|
||
(f (getValueCast? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k' k).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_alterKey_eq_self hd he
|
||
|
||
namespace Const
|
||
|
||
variable {β : Type v}
|
||
|
||
theorem maxKey!_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f} (he : (modifyKey k f l).isEmpty = false) :
|
||
(modifyKey k f l |> maxKey!) = if (maxKey! l) == k then k else (maxKey! l) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_modifyKey hd he
|
||
|
||
theorem maxKey!_modifyKey_eq_maxKey! [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
[Inhabited α] {l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f} :
|
||
(modifyKey k f l |> maxKey!) = maxKey! l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_modifyKey_eq_minKey! hd
|
||
|
||
theorem maxKey!_modifyKey_beq [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f} :
|
||
(modifyKey k f l |> maxKey!) == (maxKey! l) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_modifyKey_beq hd
|
||
|
||
theorem maxKey!_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f} (he : (alterKey k f l).isEmpty = false) :
|
||
(alterKey k f l |> maxKey!) = k ↔
|
||
(f (getValue? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k' k).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_alterKey_eq_self hd he
|
||
|
||
end Const
|
||
|
||
/-- Returns the smallest key in an associative list or `fallback` if the list is empty. -/
|
||
abbrev maxKeyD [Ord α] (xs : List ((a : α) × β a)) (fallback : α) : α :=
|
||
letI : Ord α := .opposite inferInstance; minKeyD xs fallback
|
||
|
||
theorem maxKeyD_of_perm [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l l' : List ((a : α) × β a)} {fallback} (hd : DistinctKeys l) (hp : l.Perm l') :
|
||
maxKeyD l fallback = maxKeyD l' fallback :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_of_perm hd hp
|
||
|
||
theorem maxKeyD_eq_getD_maxKey? [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} {fallback} :
|
||
maxKeyD l fallback = (maxKey? l).getD fallback :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_eq_getD_minKey?
|
||
|
||
theorem maxKey_eq_maxKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} {he fallback} :
|
||
maxKey l he = maxKeyD l fallback :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey_eq_minKeyD
|
||
|
||
theorem maxKey?_eq_some_maxKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} {fallback} (he : l.isEmpty = false) :
|
||
maxKey? l = some (maxKeyD l fallback) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey?_eq_some_minKeyD he
|
||
|
||
theorem maxKey!_eq_maxKeyD_default [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} :
|
||
maxKey! l = maxKeyD l default :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKey!_eq_minKeyD_default
|
||
|
||
theorem maxKeyD_eq_fallback [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} {fallback} (h : l.isEmpty) :
|
||
maxKeyD l fallback = fallback :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_eq_fallback h
|
||
|
||
theorem maxKeyD_eq_iff_getKey?_eq_self_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {km fallback} :
|
||
maxKeyD l fallback = km ↔
|
||
getKey? km l = some km ∧ ∀ k, containsKey k l → (compare k km).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_eq_iff_getKey?_eq_self_and_forall hd he
|
||
|
||
theorem maxKeyD_eq_iff_mem_and_forall [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
[LawfulEqOrd α] {l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(he : l.isEmpty = false) {km fallback} :
|
||
maxKeyD l fallback = km ↔ containsKey km l ∧ ∀ k, containsKey k l → (compare k km).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_eq_iff_mem_and_forall hd he
|
||
|
||
theorem maxKeyD_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v fallback} :
|
||
(insertEntry k v l |> maxKeyD <| fallback) =
|
||
((maxKey? l).elim k fun k' => if compare k' k |>.isLE then k else k') :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_insertEntry hd
|
||
|
||
theorem maxKeyD_le_maxKeyD_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {k v fallback} :
|
||
compare (maxKeyD l fallback) (insertEntry k v l |> maxKeyD <| fallback) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_insertEntry_le_minKeyD hd he
|
||
|
||
theorem self_le_maxKeyD_insertEntry [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v fallback} :
|
||
compare k (insertEntry k v l |> maxKeyD <| fallback) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_insertEntry_le_self hd
|
||
|
||
theorem containsKey_maxKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {fallback} :
|
||
containsKey (maxKeyD l fallback) l :=
|
||
letI : Ord α := .opposite inferInstance
|
||
containsKey_minKeyD hd he
|
||
|
||
theorem le_maxKeyD_of_containsKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k} (hc : containsKey k l) {fallback} :
|
||
compare k (maxKeyD l fallback) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_le_of_containsKey hd hc
|
||
|
||
theorem maxKeyD_le [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {k fallback} :
|
||
(compare (maxKeyD l fallback) k).isLE ↔ (∀ k', containsKey k' l → (compare k' k).isLE) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
le_minKeyD hd he
|
||
|
||
theorem getKey?_maxKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {fallback} :
|
||
getKey? (maxKeyD l fallback) l = some (maxKeyD l fallback) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey?_minKeyD hd he
|
||
|
||
theorem getKey_maxKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {fallback he} :
|
||
getKey (maxKeyD l fallback) l he = maxKeyD l fallback :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey_minKeyD hd
|
||
|
||
theorem getKey_maxKeyD_eq_maxKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {fallback he} :
|
||
getKey (maxKeyD l fallback) l he = maxKey l (isEmpty_eq_false_of_containsKey he) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey_minKeyD_eq_minKey hd
|
||
|
||
theorem getKey!_maxKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [Inhabited α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {fallback} :
|
||
getKey! (maxKeyD l fallback) l = maxKeyD l fallback :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKey!_minKeyD hd he
|
||
|
||
theorem getKeyD_maxKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {fallback fallback'} :
|
||
getKeyD (maxKeyD l fallback) l fallback' = maxKeyD l fallback :=
|
||
letI : Ord α := .opposite inferInstance
|
||
getKeyD_minKeyD hd he
|
||
|
||
theorem maxKeyD_eraseKey_eq_iff_beq_maxKey_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k fallback}
|
||
(he : (eraseKey k l).isEmpty = false) :
|
||
(eraseKey k l |> maxKeyD <| fallback) = maxKeyD l fallback ↔
|
||
(k == (maxKeyD l fallback)) = false :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_eraseKey_eq_iff_beq_minKey_eq_false hd he
|
||
|
||
theorem maxKeyD_eraseKey_eq_iff_beq_maxKeyD_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k fallback}
|
||
(he : (eraseKey k l).isEmpty = false) :
|
||
(eraseKey k l |> maxKeyD <| fallback) = maxKeyD l fallback ↔
|
||
(k == (maxKeyD l fallback)) = false :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_eraseKey_eq_iff_beq_minKeyD_eq_false hd he
|
||
|
||
theorem maxKeyD_eraseKey_eq_of_beq_maxKeyD_eq_false [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k fallback}
|
||
(he : (eraseKey k l).isEmpty = false) : (heq : (k == maxKeyD l fallback) = false) →
|
||
(eraseKey k l |> maxKeyD <| fallback) = maxKeyD l fallback:=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_eraseKey_eq_of_beq_minKeyD_eq_false hd he
|
||
|
||
theorem maxKeyD_eraseKey_le_maxKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k} (he : (eraseKey k l).isEmpty = false)
|
||
{fallback} :
|
||
compare (eraseKey k l |> maxKeyD <| fallback) (maxKeyD l fallback) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_le_minKeyD_erase hd he
|
||
|
||
theorem maxKeyD_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v fallback} :
|
||
(insertEntryIfNew k v l |> maxKeyD <| fallback) =
|
||
(maxKey? l).elim k fun k' => if compare k' k = .lt then k else k' :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_insertEntryIfNew hd
|
||
|
||
theorem maxKeyD_le_maxKeyD_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) (he : l.isEmpty = false) {k v fallback} :
|
||
compare (maxKeyD l fallback) (insertEntryIfNew k v l |> maxKeyD <| fallback) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_insertEntryIfNew_le_minKeyD hd he
|
||
|
||
theorem self_le_maxKeyD_insertEntryIfNew [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k v fallback} :
|
||
compare k (insertEntryIfNew k v l |> maxKeyD <| fallback) |>.isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_insertEntryIfNew_le_self hd
|
||
|
||
theorem maxKeyD_eq_getLastD_keys [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l)
|
||
(ho : l.Pairwise fun a b => compare a.1 b.1 = .lt) {fallback} :
|
||
maxKeyD l fallback = (keys l).getLastD fallback := by
|
||
simp only [List.getLastD_eq_getLast?, maxKeyD_eq_getD_maxKey?,
|
||
maxKey?_eq_getLast?_keys hd ho]
|
||
|
||
theorem maxKeyD_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k f fallback} :
|
||
(modifyKey k f l |> maxKeyD <| fallback) = maxKeyD l fallback :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_modifyKey hd
|
||
|
||
theorem maxKeyD_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
{l : List ((a : α) × β a)} (hd : DistinctKeys l) {k f fallback}
|
||
(he : (alterKey k f l).isEmpty = false) :
|
||
(alterKey k f l |> maxKeyD <| fallback) = k ↔
|
||
(f (getValueCast? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k' k).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_alterKey_eq_self hd he
|
||
|
||
namespace Const
|
||
|
||
variable {β : Type v}
|
||
|
||
theorem maxKeyD_modifyKey [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f} (he : (modifyKey k f l).isEmpty = false)
|
||
{fallback} :
|
||
(modifyKey k f l |> maxKeyD <| fallback) = if (maxKeyD l fallback) == k then k else (maxKeyD l fallback) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_modifyKey hd he
|
||
|
||
theorem maxKeyD_modifyKey_eq_maxKeyD [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α] [LawfulEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f fallback} :
|
||
(modifyKey k f l |> maxKeyD <| fallback) = maxKeyD l fallback :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_modifyKey_eq_minKeyD hd
|
||
|
||
theorem maxKeyD_modifyKey_beq [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f fallback} :
|
||
(modifyKey k f l |> maxKeyD <| fallback) == (maxKeyD l fallback) :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_modifyKey_beq hd
|
||
|
||
theorem maxKeyD_alterKey_eq_self [Ord α] [TransOrd α] [BEq α] [LawfulBEqOrd α]
|
||
{l : List ((_ : α) × β)} (hd : DistinctKeys l) {k f} (he : (alterKey k f l).isEmpty = false)
|
||
{fallback} :
|
||
(alterKey k f l |> maxKeyD <| fallback) = k ↔
|
||
(f (getValue? k l)).isSome ∧ ∀ k', containsKey k' l → (compare k' k).isLE :=
|
||
letI : Ord α := .opposite inferInstance
|
||
minKeyD_alterKey_eq_self hd he
|
||
|
||
end Const
|
||
|
||
end Max
|
||
|
||
end Std.Internal.List
|