File: Mathlib/Data/List/AList.lean

full_name: AList.entries
code: /-- `AList β` is a key-value map stored as a `List` (i.e. a linked list).
  It is a wrapper around certain `List` functions with the added constraint
  that the list have unique keys. -/
structure AList (β : α → Type v) : Type max u v where
  /-- The underlying `List` of an `AList` -/
  entries : List (Sigma β)
  /-- There are no duplicate keys in `entries` -/
  nodupKeys : entries.NodupKeys
goal: List (Sigma β)

full_name: AList.nodupKeys
code: /-- `AList β` is a key-value map stored as a `List` (i.e. a linked list).
  It is a wrapper around certain `List` functions with the added constraint
  that the list have unique keys. -/
structure AList (β : α → Type v) : Type max u v where
  /-- The underlying `List` of an `AList` -/
  entries : List (Sigma β)
  /-- There are no duplicate keys in `entries` -/
  nodupKeys : entries.NodupKeys
goal: self.entries.NodupKeys

full_name: AList
code: /-- `AList β` is a key-value map stored as a `List` (i.e. a linked list).
  It is a wrapper around certain `List` functions with the added constraint
  that the list have unique keys. -/
structure AList (β : α → Type v) : Type max u v where
  /-- The underlying `List` of an `AList` -/
  entries : List (Sigma β)
  /-- There are no duplicate keys in `entries` -/
  nodupKeys : entries.NodupKeys
goal: Type (max u v)

full_name: List.toAList
code: /-- Given `l : List (Sigma β)`, create a term of type `AList β` by removing
entries with duplicate keys. -/
def List.toAList [DecidableEq α] {β : α → Type v} (l : List (Sigma β)) : AList β 
goal: AList β

full_name: AList.ext
code: @[ext]
theorem ext : ∀ {s t : AList β}, s.entries = t.entries → s = t
  
goal: s.entries = t.entries → s = t

full_name: AList.ext_iff
code: protected theorem ext_iff {s t : AList β} : s = t ↔ s.entries = t.entries 
goal: s = t ↔ s.entries = t.entries

full_name: AList.instDecidableEq
code: instance [DecidableEq α] [∀ a, DecidableEq (β a)] : DecidableEq (AList β) 
goal: DecidableEq (AList β)

full_name: AList.keys
code: /-- The list of keys of an association list. -/
def keys (s : AList β) : List α 
goal: List α

full_name: AList.keys_nodup
code: theorem keys_nodup (s : AList β) : s.keys.Nodup 
goal: s.keys.Nodup

full_name: AList.instMembership
code: /-- The predicate `a ∈ s` means that `s` has a value associated to the key `a`. -/
instance : Membership α (AList β) 
goal: Membership α (AList β)

full_name: AList.mem_keys
code: theorem mem_keys {a : α} {s : AList β} : a ∈ s ↔ a ∈ s.keys 
goal: a ∈ s ↔ a ∈ s.keys

full_name: AList.mem_of_perm
code: theorem mem_of_perm {a : α} {s₁ s₂ : AList β} (p : s₁.entries ~ s₂.entries) : a ∈ s₁ ↔ a ∈ s₂ 
goal: a ∈ s₁ ↔ a ∈ s₂

full_name: AList.instEmptyCollection
code: /-- The empty association list. -/
instance : EmptyCollection (AList β) 
goal: EmptyCollection (AList β)

full_name: AList.instInhabited
code: instance : Inhabited (AList β) 
goal: Inhabited (AList β)

full_name: AList.not_mem_empty
code: @[simp]
theorem not_mem_empty (a : α) : a ∉ (∅ : AList β) 
goal: a ∉ ∅

full_name: AList.empty_entries
code: @[simp]
theorem empty_entries : (∅ : AList β).entries = [] 
goal: ∅.entries = []

full_name: AList.keys_empty
code: @[simp]
theorem keys_empty : (∅ : AList β).keys = [] 
goal: ∅.keys = []

full_name: AList.singleton
code: /-- The singleton association list. -/
def singleton (a : α) (b : β a) : AList β 
goal: AList β

full_name: AList.singleton_entries
code: @[simp]
theorem singleton_entries (a : α) (b : β a) : (singleton a b).entries = [Sigma.mk a b] 
goal: (AList.singleton a b).entries = [⟨a, b⟩]

full_name: AList.keys_singleton
code: @[simp]
theorem keys_singleton (a : α) (b : β a) : (singleton a b).keys = [a] 
goal: (AList.singleton a b).keys = [a]

full_name: AList.lookup
code: /-- Look up the value associated to a key in an association list. -/
def lookup (a : α) (s : AList β) : Option (β a) 
goal: Option (β a)

full_name: AList.lookup_empty
code: @[simp]
theorem lookup_empty (a) : lookup a (∅ : AList β) = none 
goal: AList.lookup a ∅ = none

full_name: AList.lookup_isSome
code: theorem lookup_isSome {a : α} {s : AList β} : (s.lookup a).isSome ↔ a ∈ s 
goal: (AList.lookup a s).isSome = true ↔ a ∈ s

full_name: AList.lookup_eq_none
code: theorem lookup_eq_none {a : α} {s : AList β} : lookup a s = none ↔ a ∉ s 
goal: AList.lookup a s = none ↔ a ∉ s

full_name: AList.mem_lookup_iff
code: theorem mem_lookup_iff {a : α} {b : β a} {s : AList β} :
    b ∈ lookup a s ↔ Sigma.mk a b ∈ s.entries 
goal: b ∈ AList.lookup a s ↔ ⟨a, b⟩ ∈ s.entries

full_name: AList.perm_lookup
code: theorem perm_lookup {a : α} {s₁ s₂ : AList β} (p : s₁.entries ~ s₂.entries) :
    s₁.lookup a = s₂.lookup a 
goal: AList.lookup a s₁ = AList.lookup a s₂

full_name: AList.instDecidableMem
code: instance (a : α) (s : AList β) : Decidable (a ∈ s) 
goal: Decidable (a ∈ s)

full_name: AList.keys_subset_keys_of_entries_subset_entries
code: theorem keys_subset_keys_of_entries_subset_entries
    {s₁ s₂ : AList β} (h : s₁.entries ⊆ s₂.entries) : s₁.keys ⊆ s₂.keys 
goal: s₁.keys ⊆ s₂.keys

full_name: AList.replace
code: /-- Replace a key with a given value in an association list.
  If the key is not present it does nothing. -/
def replace (a : α) (b : β a) (s : AList β) : AList β 
goal: AList β

full_name: AList.keys_replace
code: @[simp]
theorem keys_replace (a : α) (b : β a) (s : AList β) : (replace a b s).keys = s.keys 
goal: (AList.replace a b s).keys = s.keys

full_name: AList.mem_replace
code: @[simp]
theorem mem_replace {a a' : α} {b : β a} {s : AList β} : a' ∈ replace a b s ↔ a' ∈ s 
goal: a' ∈ AList.replace a b s ↔ a' ∈ s

full_name: AList.perm_replace
code: theorem perm_replace {a : α} {b : β a} {s₁ s₂ : AList β} :
    s₁.entries ~ s₂.entries → (replace a b s₁).entries ~ (replace a b s₂).entries 
goal: s₁.entries ~ s₂.entries → (AList.replace a b s₁).entries ~ (AList.replace a b s₂).entries

full_name: AList.foldl
code: /-- Fold a function over the key-value pairs in the map. -/
def foldl {δ : Type w} (f : δ → ∀ a, β a → δ) (d : δ) (m : AList β) : δ 
goal: δ

full_name: AList.erase
code: /-- Erase a key from the map. If the key is not present, do nothing. -/
def erase (a : α) (s : AList β) : AList β 
goal: AList β

full_name: AList.keys_erase
code: @[simp]
theorem keys_erase (a : α) (s : AList β) : (erase a s).keys = s.keys.erase a 
goal: (AList.erase a s).keys = s.keys.erase a

full_name: AList.mem_erase
code: @[simp]
theorem mem_erase {a a' : α} {s : AList β} : a' ∈ erase a s ↔ a' ≠ a ∧ a' ∈ s 
goal: a' ∈ AList.erase a s ↔ a' ≠ a ∧ a' ∈ s

full_name: AList.perm_erase
code: theorem perm_erase {a : α} {s₁ s₂ : AList β} :
    s₁.entries ~ s₂.entries → (erase a s₁).entries ~ (erase a s₂).entries 
goal: s₁.entries ~ s₂.entries → (AList.erase a s₁).entries ~ (AList.erase a s₂).entries

full_name: AList.lookup_erase
code: @[simp]
theorem lookup_erase (a) (s : AList β) : lookup a (erase a s) = none 
goal: AList.lookup a (AList.erase a s) = none

full_name: AList.lookup_erase_ne
code: @[simp]
theorem lookup_erase_ne {a a'} {s : AList β} (h : a ≠ a') : lookup a (erase a' s) = lookup a s 
goal: AList.lookup a (AList.erase a' s) = AList.lookup a s

full_name: AList.erase_erase
code: theorem erase_erase (a a' : α) (s : AList β) : (s.erase a).erase a' = (s.erase a').erase a 
goal: AList.erase a' (AList.erase a s) = AList.erase a (AList.erase a' s)

full_name: AList.insert
code: /-- Insert a key-value pair into an association list and erase any existing pair
  with the same key. -/
def insert (a : α) (b : β a) (s : AList β) : AList β 
goal: AList β

full_name: AList.insert_entries
code: @[simp]
theorem insert_entries {a} {b : β a} {s : AList β} :
    (insert a b s).entries = Sigma.mk a b :: kerase a s.entries 
goal: (AList.insert a b s).entries = ⟨a, b⟩ :: List.kerase a s.entries

full_name: AList.insert_entries_of_neg
code: theorem insert_entries_of_neg {a} {b : β a} {s : AList β} (h : a ∉ s) :
    (insert a b s).entries = ⟨a, b⟩ :: s.entries 
goal: (AList.insert a b s).entries = ⟨a, b⟩ :: s.entries

full_name: AList.insert_of_neg
code: theorem insert_of_neg {a} {b : β a} {s : AList β} (h : a ∉ s) :
    insert a b s = ⟨⟨a, b⟩ :: s.entries, nodupKeys_cons.2 ⟨h, s.2⟩⟩ 
goal: AList.insert a b s = { entries := ⟨a, b⟩ :: s.entries, nodupKeys := ⋯ }

full_name: AList.insert_empty
code: @[simp]
theorem insert_empty (a) (b : β a) : insert a b ∅ = singleton a b 
goal: AList.insert a b ∅ = AList.singleton a b

full_name: AList.mem_insert
code: @[simp]
theorem mem_insert {a a'} {b' : β a'} (s : AList β) : a ∈ insert a' b' s ↔ a = a' ∨ a ∈ s 
goal: a ∈ AList.insert a' b' s ↔ a = a' ∨ a ∈ s

full_name: AList.keys_insert
code: @[simp]
theorem keys_insert {a} {b : β a} (s : AList β) : (insert a b s).keys = a :: s.keys.erase a 
goal: (AList.insert a b s).keys = a :: s.keys.erase a

full_name: AList.perm_insert
code: theorem perm_insert {a} {b : β a} {s₁ s₂ : AList β} (p : s₁.entries ~ s₂.entries) :
    (insert a b s₁).entries ~ (insert a b s₂).entries 
goal: (AList.insert a b s₁).entries ~ (AList.insert a b s₂).entries

full_name: AList.lookup_insert
code: @[simp]
theorem lookup_insert {a} {b : β a} (s : AList β) : lookup a (insert a b s) = some b 
goal: AList.lookup a (AList.insert a b s) = some b

full_name: AList.lookup_insert_ne
code: @[simp]
theorem lookup_insert_ne {a a'} {b' : β a'} {s : AList β} (h : a ≠ a') :
    lookup a (insert a' b' s) = lookup a s 
goal: AList.lookup a (AList.insert a' b' s) = AList.lookup a s

full_name: AList.lookup_insert_eq_none
code: @[simp] theorem lookup_insert_eq_none {l : AList β} {k k' : α} {v : β k} :
    (l.insert k v).lookup k' = none ↔ (k' ≠ k) ∧ l.lookup k' = none 
goal: AList.lookup k' (AList.insert k v l) = none ↔ k' ≠ k ∧ AList.lookup k' l = none

full_name: AList.lookup_to_alist
code: @[simp]
theorem lookup_to_alist {a} (s : List (Sigma β)) : lookup a s.toAList = s.dlookup a 
goal: AList.lookup a s.toAList = List.dlookup a s

full_name: AList.insert_insert
code: @[simp]
theorem insert_insert {a} {b b' : β a} (s : AList β) :
    (s.insert a b).insert a b' = s.insert a b' 
goal: AList.insert a b' (AList.insert a b s) = AList.insert a b' s

full_name: AList.insert_insert_of_ne
code: theorem insert_insert_of_ne {a a'} {b : β a} {b' : β a'} (s : AList β) (h : a ≠ a') :
    ((s.insert a b).insert a' b').entries ~ ((s.insert a' b').insert a b).entries 
goal: (AList.insert a' b' (AList.insert a b s)).entries ~ (AList.insert a b (AList.insert a' b' s)).entries

full_name: AList.insert_singleton_eq
code: @[simp]
theorem insert_singleton_eq {a : α} {b b' : β a} : insert a b (singleton a b') = singleton a b 
goal: AList.insert a b (AList.singleton a b') = AList.singleton a b

full_name: AList.entries_toAList
code: @[simp]
theorem entries_toAList (xs : List (Sigma β)) : (List.toAList xs).entries = dedupKeys xs 
goal: xs.toAList.entries = xs.dedupKeys

full_name: AList.toAList_cons
code: theorem toAList_cons (a : α) (b : β a) (xs : List (Sigma β)) :
    List.toAList (⟨a, b⟩ :: xs) = insert a b xs.toAList 
goal: (⟨a, b⟩ :: xs).toAList = AList.insert a b xs.toAList

full_name: AList.mk_cons_eq_insert
code: theorem mk_cons_eq_insert (c : Sigma β) (l : List (Sigma β)) (h : (c :: l).NodupKeys) :
    (⟨c :: l, h⟩ : AList β) = insert c.1 c.2 ⟨l, nodupKeys_of_nodupKeys_cons h⟩ 
goal: { entries := c :: l, nodupKeys := h } = AList.insert c.fst c.snd { entries := l, nodupKeys := ⋯ }

full_name: AList.insertRec
code: /-- Recursion on an `AList`, using `insert`. Use as `induction l`. -/
@[elab_as_elim, induction_eliminator]
def insertRec {C : AList β → Sort*} (H0 : C ∅)
    (IH : ∀ (a : α) (b : β a) (l : AList β), a ∉ l → C l → C (l.insert a b)) :
    ∀ l : AList β, C l
  
goal: C l

full_name: AList.insertRec_empty
code: @[simp]
theorem insertRec_empty {C : AList β → Sort*} (H0 : C ∅)
    (IH : ∀ (a : α) (b : β a) (l : AList β), a ∉ l → C l → C (l.insert a b)) :
    @insertRec α β _ C H0 IH ∅ = H0 
goal: AList.insertRec H0 IH ∅ = H0

full_name: AList.insertRec_insert
code: theorem insertRec_insert {C : AList β → Sort*} (H0 : C ∅)
    (IH : ∀ (a : α) (b : β a) (l : AList β), a ∉ l → C l → C (l.insert a b)) {c : Sigma β}
    {l : AList β} (h : c.1 ∉ l) :
    @insertRec α β _ C H0 IH (l.insert c.1 c.2) = IH c.1 c.2 l h (@insertRec α β _ C H0 IH l) 
goal: AList.insertRec H0 IH (AList.insert c.fst c.snd l) = IH c.fst c.snd l h (AList.insertRec H0 IH l)

full_name: AList.insertRec_insert_mk
code: theorem insertRec_insert_mk {C : AList β → Sort*} (H0 : C ∅)
    (IH : ∀ (a : α) (b : β a) (l : AList β), a ∉ l → C l → C (l.insert a b)) {a : α} (b : β a)
    {l : AList β} (h : a ∉ l) :
    @insertRec α β _ C H0 IH (l.insert a b) = IH a b l h (@insertRec α β _ C H0 IH l) 
goal: AList.insertRec H0 IH (AList.insert a b l) = IH a b l h (AList.insertRec H0 IH l)

full_name: AList.extract
code: /-- Erase a key from the map, and return the corresponding value, if found. -/
def extract (a : α) (s : AList β) : Option (β a) × AList β 
goal: Option (β a) × AList β

full_name: AList.extract_eq_lookup_erase
code: @[simp]
theorem extract_eq_lookup_erase (a : α) (s : AList β) : extract a s = (lookup a s, erase a s) 
goal: AList.extract a s = (AList.lookup a s, AList.erase a s)

full_name: AList.union
code: /-- `s₁ ∪ s₂` is the key-based union of two association lists. It is
left-biased: if there exists an `a ∈ s₁`, `lookup a (s₁ ∪ s₂) = lookup a s₁`.
-/
def union (s₁ s₂ : AList β) : AList β 
goal: AList β

full_name: AList.instUnion
code: instance : Union (AList β) 
goal: Union (AList β)

full_name: AList.union_entries
code: @[simp]
theorem union_entries {s₁ s₂ : AList β} : (s₁ ∪ s₂).entries = kunion s₁.entries s₂.entries 
goal: (s₁ ∪ s₂).entries = s₁.entries.kunion s₂.entries

full_name: AList.empty_union
code: @[simp]
theorem empty_union {s : AList β} : (∅ : AList β) ∪ s = s 
goal: ∅ ∪ s = s

full_name: AList.union_empty
code: @[simp]
theorem union_empty {s : AList β} : s ∪ (∅ : AList β) = s 
goal: s ∪ ∅ = s

full_name: AList.mem_union
code: @[simp]
theorem mem_union {a} {s₁ s₂ : AList β} : a ∈ s₁ ∪ s₂ ↔ a ∈ s₁ ∨ a ∈ s₂ 
goal: a ∈ s₁ ∪ s₂ ↔ a ∈ s₁ ∨ a ∈ s₂

full_name: AList.perm_union
code: theorem perm_union {s₁ s₂ s₃ s₄ : AList β} (p₁₂ : s₁.entries ~ s₂.entries)
    (p₃₄ : s₃.entries ~ s₄.entries) : (s₁ ∪ s₃).entries ~ (s₂ ∪ s₄).entries 
goal: (s₁ ∪ s₃).entries ~ (s₂ ∪ s₄).entries

full_name: AList.union_erase
code: theorem union_erase (a : α) (s₁ s₂ : AList β) : erase a (s₁ ∪ s₂) = erase a s₁ ∪ erase a s₂ 
goal: AList.erase a (s₁ ∪ s₂) = AList.erase a s₁ ∪ AList.erase a s₂

full_name: AList.lookup_union_left
code: @[simp]
theorem lookup_union_left {a} {s₁ s₂ : AList β} : a ∈ s₁ → lookup a (s₁ ∪ s₂) = lookup a s₁ 
goal: a ∈ s₁ → AList.lookup a (s₁ ∪ s₂) = AList.lookup a s₁

full_name: AList.lookup_union_right
code: @[simp]
theorem lookup_union_right {a} {s₁ s₂ : AList β} : a ∉ s₁ → lookup a (s₁ ∪ s₂) = lookup a s₂ 
goal: a ∉ s₁ → AList.lookup a (s₁ ∪ s₂) = AList.lookup a s₂

full_name: AList.mem_lookup_union
code: theorem mem_lookup_union {a} {b : β a} {s₁ s₂ : AList β} :
    b ∈ lookup a (s₁ ∪ s₂) ↔ b ∈ lookup a s₁ ∨ a ∉ s₁ ∧ b ∈ lookup a s₂ 
goal: b ∈ AList.lookup a (s₁ ∪ s₂) ↔ b ∈ AList.lookup a s₁ ∨ a ∉ s₁ ∧ b ∈ AList.lookup a s₂

full_name: AList.lookup_union_eq_some
code: @[simp]
theorem lookup_union_eq_some {a} {b : β a} {s₁ s₂ : AList β} :
    lookup a (s₁ ∪ s₂) = some b ↔ lookup a s₁ = some b ∨ a ∉ s₁ ∧ lookup a s₂ = some b 
goal: AList.lookup a (s₁ ∪ s₂) = some b ↔ AList.lookup a s₁ = some b ∨ a ∉ s₁ ∧ AList.lookup a s₂ = some b

full_name: AList.mem_lookup_union_middle
code: theorem mem_lookup_union_middle {a} {b : β a} {s₁ s₂ s₃ : AList β} :
    b ∈ lookup a (s₁ ∪ s₃) → a ∉ s₂ → b ∈ lookup a (s₁ ∪ s₂ ∪ s₃) 
goal: b ∈ AList.lookup a (s₁ ∪ s₃) → a ∉ s₂ → b ∈ AList.lookup a (s₁ ∪ s₂ ∪ s₃)

full_name: AList.insert_union
code: theorem insert_union {a} {b : β a} {s₁ s₂ : AList β} :
    insert a b (s₁ ∪ s₂) = insert a b s₁ ∪ s₂ 
goal: AList.insert a b (s₁ ∪ s₂) = AList.insert a b s₁ ∪ s₂

full_name: AList.union_assoc
code: theorem union_assoc {s₁ s₂ s₃ : AList β} : (s₁ ∪ s₂ ∪ s₃).entries ~ (s₁ ∪ (s₂ ∪ s₃)).entries 
goal: (s₁ ∪ s₂ ∪ s₃).entries ~ (s₁ ∪ (s₂ ∪ s₃)).entries

full_name: AList.Disjoint
code: /-- Two associative lists are disjoint if they have no common keys. -/
def Disjoint (s₁ s₂ : AList β) : Prop 
goal: Prop

full_name: AList.union_comm_of_disjoint
code: theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries 
goal: (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries