l3lab/ntp-mathlib huggingface dataset:
theorem keys_subset_keys_of_entries_subset_entries
    {s₁ s₂ : AList β} (h : s₁.entries ⊆ s₂.entries) : s₁.keys ⊆ s₂.keys := by
  intro k hk
  letI : DecidableEq α := Classical.decEq α
  have := h (mem_lookup_iff.1 (Option.get_mem (lookup_isSome.2 hk)))
  rw [← mem_lookup_iff, Option.mem_def] at this
  rw [← mem_keys, ← lookup_isSome, this]
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : s₁.entries ⊆ s₂.entries
k : α
hk : k ∈ keys s₁
this✝ : DecidableEq α := Classical.decEq α
this : lookup k s₂ = some (Option.get (lookup k s₁) (_ : Option.isSome (lookup k s₁) = true))
⊢ Option.isSome (some (Option.get (lookup k s₁) (_ : Option.isSome (lookup k s₁) = true))) = true

Next tactic:
exact Option.isSome_some
@[simp]
theorem mem_replace {a a' : α} {b : β a} {s : AList β} : a' ∈ replace a b s ↔ a' ∈ s := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a a' : α
b : β a
s : AList β
⊢ a' ∈ replace a b s ↔ a' ∈ s

Next tactic:
rw [mem_keys, keys_replace, ← mem_keys]
@[simp]
theorem mem_erase {a a' : α} {s : AList β} : a' ∈ erase a s ↔ a' ≠ a ∧ a' ∈ s := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a a' : α
s : AList β
⊢ a' ∈ erase a s ↔ a' ≠ a ∧ a' ∈ s

Next tactic:
rw [mem_keys, keys_erase, s.keys_nodup.mem_erase_iff, ← mem_keys]
theorem insert_entries_of_neg {a} {b : β a} {s : AList β} (h : a ∉ s) :
    (insert a b s).entries = ⟨a, b⟩ :: s.entries := by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s : AList β
h : a ∉ s
⊢ (insert a b s).entries = { fst := a, snd := b } :: s.entries

Next tactic:
rw [insert_entries, kerase_of_not_mem_keys h]
@[simp]
theorem keys_insert {a} {b : β a} (s : AList β) : (insert a b s).keys = a :: s.keys.erase a := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s : AList β
⊢ keys (insert a b s) = a :: List.erase (keys s) a

Next tactic:
simp [insert, keys, keys_kerase]
theorem perm_insert {a} {b : β a} {s₁ s₂ : AList β} (p : s₁.entries ~ s₂.entries) :
    (insert a b s₁).entries ~ (insert a b s₂).entries := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s₁ s₂ : AList β
p : s₁.entries ~ s₂.entries
⊢ (insert a b s₁).entries ~ (insert a b s₂).entries

Next tactic:
simp only [insert_entries]
theorem perm_insert {a} {b : β a} {s₁ s₂ : AList β} (p : s₁.entries ~ s₂.entries) :
    (insert a b s₁).entries ~ (insert a b s₂).entries := by
  simp only [insert_entries]; 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s₁ s₂ : AList β
p : s₁.entries ~ s₂.entries
⊢ { fst := a, snd := b } :: kerase a s₁.entries ~ { fst := a, snd := b } :: kerase a s₂.entries

Next tactic:
exact p.kinsert s₁.nodupKeys
@[simp]
theorem lookup_insert {a} {b : β a} (s : AList β) : lookup a (insert a b s) = some b := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s : AList β
⊢ lookup a (insert a b s) = some b

Next tactic:
simp only [lookup, insert, dlookup_kinsert]
@[simp]
theorem lookup_to_alist {a} (s : List (Sigma β)) : lookup a s.toAList = s.dlookup a := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s : List (Sigma β)
⊢ lookup a (toAList s) = dlookup a s

Next tactic:
rw [List.toAList, lookup, dlookup_dedupKeys]
@[simp]
theorem insert_insert {a} {b b' : β a} (s : AList β) :
    (s.insert a b).insert a b' = s.insert a b' := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b b' : β a
s : AList β
⊢ insert a b' (insert a b s) = insert a b' s

Next tactic:
ext : 1
@[simp]
theorem insert_insert {a} {b b' : β a} (s : AList β) :
    (s.insert a b).insert a b' = s.insert a b' := by
  ext : 1; 

Proof state:
case a
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b b' : β a
s : AList β
⊢ (insert a b' (insert a b s)).entries = (insert a b' s).entries

Next tactic:
simp only [AList.insert_entries, List.kerase_cons_eq]
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 := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a a' : α
b : β a
b' : β a'
s : AList β
h : a ≠ a'
⊢ (insert a' b' (insert a b s)).entries ~ (insert a b (insert a' b' s)).entries

Next tactic:
simp only [insert_entries]
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 := by
  simp only [insert_entries]; 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a a' : α
b : β a
b' : β a'
s : AList β
h : a ≠ a'
⊢ { fst := a', snd := b' } :: kerase a' ({ fst := a, snd := b } :: kerase a s.entries) ~
    { fst := a, snd := b } :: kerase a ({ fst := a', snd := b' } :: kerase a' s.entries)

Next tactic:
rw [kerase_cons_ne, kerase_cons_ne, kerase_comm] <;>
    [apply Perm.swap; exact h; exact h.symm]
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 := by
  simp only [insert_entries]; 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a a' : α
b : β a
b' : β a'
s : AList β
h : a ≠ a'
⊢ { fst := a', snd := b' } :: kerase a' ({ fst := a, snd := b } :: kerase a s.entries) ~
    { fst := a, snd := b } :: kerase a ({ fst := a', snd := b' } :: kerase a' s.entries)

Next tactic:
rw [kerase_cons_ne, kerase_cons_ne, kerase_comm]
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 := by
  simp only [insert_entries]; rw [kerase_cons_ne, kerase_cons_ne, kerase_comm] <;>
    [

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a a' : α
b : β a
b' : β a'
s : AList β
h : a ≠ a'
⊢ { fst := a', snd := b' } :: { fst := a, snd := b } :: kerase a (kerase a' s.entries) ~
    { fst := a, snd := b } :: { fst := a', snd := b' } :: kerase a (kerase a' s.entries)

Next tactic:
apply Perm.swap
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 := by
  simp only [insert_entries]; rw [kerase_cons_ne, kerase_cons_ne, kerase_comm] <;>
    [apply Perm.swap; 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a a' : α
b : β a
b' : β a'
s : AList β
h : a ≠ a'
⊢ a ≠ { fst := a', snd := b' }.fst

Next tactic:
exact h
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 := by
  simp only [insert_entries]; rw [kerase_cons_ne, kerase_cons_ne, kerase_comm] <;>
    [apply Perm.swap; exact h; 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a a' : α
b : β a
b' : β a'
s : AList β
h : a ≠ a'
⊢ a' ≠ { fst := a, snd := b }.fst

Next tactic:
exact h.symm
@[simp]
theorem insert_singleton_eq {a : α} {b b' : β a} : insert a b (singleton a b') = singleton a b :=
  ext <| by
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b b' : β a
⊢ (insert a b (singleton a b')).entries = (singleton a b).entries

Next tactic:
simp only [AList.insert_entries, List.kerase_cons_eq, and_self_iff, AList.singleton_entries,
      heq_iff_eq, eq_self_iff_true]
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⟩ := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
c : Sigma β
l : List (Sigma β)
h : NodupKeys (c :: l)
⊢ { entries := c :: l, nodupKeys := h } = insert c.fst c.snd { entries := l, nodupKeys := (_ : NodupKeys l) }

Next tactic:
simpa [insert] using (kerase_of_not_mem_keys <| not_mem_keys_of_nodupKeys_cons h).symm
/-- Recursion on an `AList`, using `insert`. Use as `induction l using AList.insertRec`. -/
@[elab_as_elim]
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
  | ⟨[], _⟩ => H0
  | ⟨c :: l, h⟩ => by
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
c : Sigma β
l : List (Sigma β)
h : NodupKeys (c :: l)
⊢ C { entries := c :: l, nodupKeys := h }

Next tactic:
rw [mk_cons_eq_insert]
/-- Recursion on an `AList`, using `insert`. Use as `induction l using AList.insertRec`. -/
@[elab_as_elim]
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
  | ⟨[], _⟩ => H0
  | ⟨c :: l, h⟩ => by
    rw [mk_cons_eq_insert]
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
c : Sigma β
l : List (Sigma β)
h : NodupKeys (c :: l)
⊢ C (insert c.fst c.snd { entries := l, nodupKeys := (_ : NodupKeys l) })

Next tactic:
refine' IH _ _ _ _ (insertRec H0 IH _)
/-- Recursion on an `AList`, using `insert`. Use as `induction l using AList.insertRec`. -/
@[elab_as_elim]
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
  | ⟨[], _⟩ => H0
  | ⟨c :: l, h⟩ => by
    rw [mk_cons_eq_insert]
    refine' IH _ _ _ _ (insertRec H0 IH _)
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
c : Sigma β
l : List (Sigma β)
h : NodupKeys (c :: l)
⊢ c.fst ∉ { entries := l, nodupKeys := (_ : NodupKeys l) }

Next tactic:
exact not_mem_keys_of_nodupKeys_cons h
example (l : AList β) : True := by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
l : AList β
⊢ True

Next tactic:
induction l using AList.insertRec
example (l : AList β) : True := by induction l using AList.insertRec <;> 

Proof state:
case H0
α : Type u
β : α → Type v
inst✝ : DecidableEq α
⊢ True

Next tactic:
trivial
example (l : AList β) : True := by induction l using AList.insertRec <;> 

Proof state:
case IH
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a✝² : α
b✝ : β a✝²
l✝ : AList β
a✝¹ : a✝² ∉ l✝
a✝ : True
⊢ True

Next tactic:
trivial
@[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 := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
⊢ insertRec H0 IH ∅ = H0

Next tactic:
change @insertRec α β _ C H0 IH ⟨[], _⟩ = H0
@[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 := by
  change @insertRec α β _ C H0 IH ⟨[], _⟩ = H0
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
⊢ insertRec H0 IH { entries := [], nodupKeys := (_ : NodupKeys []) } = H0

Next tactic:
rw [insertRec]
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) := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
c : Sigma β
l : AList β
h : c.fst ∉ l
⊢ insertRec H0 IH (insert c.fst c.snd l) = IH c.fst c.snd l h (insertRec H0 IH l)

Next tactic:
cases' l with l hl
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) := by
  cases' l with l hl
  

Proof state:
case mk
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
c : Sigma β
l : List (Sigma β)
hl : NodupKeys l
h : c.fst ∉ { entries := l, nodupKeys := hl }
⊢ insertRec H0 IH (insert c.fst c.snd { entries := l, nodupKeys := hl }) =
    IH c.fst c.snd { entries := l, nodupKeys := hl } h (insertRec H0 IH { entries := l, nodupKeys := hl })

Next tactic:
suffices HEq (@insertRec α β _ C H0 IH ⟨c :: l, nodupKeys_cons.2 ⟨h, hl⟩⟩)
      (IH c.1 c.2 ⟨l, hl⟩ h (@insertRec α β _ C H0 IH ⟨l, hl⟩)) by
    cases c
    apply eq_of_heq
    convert this <;> rw [insert_of_neg h]
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) := by
  cases' l with l hl
  suffices HEq (@insertRec α β _ C H0 IH ⟨c :: l, nodupKeys_cons.2 ⟨h, hl⟩⟩)
      (IH c.1 c.2 ⟨l, hl⟩ h (@insertRec α β _ C H0 IH ⟨l, hl⟩)) by
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
c : Sigma β
l : List (Sigma β)
hl : NodupKeys l
h : c.fst ∉ { entries := l, nodupKeys := hl }
this :
  HEq (insertRec H0 IH { entries := c :: l, nodupKeys := (_ : NodupKeys (c :: l)) })
    (IH c.fst c.snd { entries := l, nodupKeys := hl } h (insertRec H0 IH { entries := l, nodupKeys := hl }))
⊢ insertRec H0 IH (insert c.fst c.snd { entries := l, nodupKeys := hl }) =
    IH c.fst c.snd { entries := l, nodupKeys := hl } h (insertRec H0 IH { entries := l, nodupKeys := hl })

Next tactic:
cases c
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) := by
  cases' l with l hl
  suffices HEq (@insertRec α β _ C H0 IH ⟨c :: l, nodupKeys_cons.2 ⟨h, hl⟩⟩)
      (IH c.1 c.2 ⟨l, hl⟩ h (@insertRec α β _ C H0 IH ⟨l, hl⟩)) by
    cases c
    

Proof state:
case mk
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
l : List (Sigma β)
hl : NodupKeys l
fst✝ : α
snd✝ : β fst✝
h : { fst := fst✝, snd := snd✝ }.fst ∉ { entries := l, nodupKeys := hl }
this :
  HEq
    (insertRec H0 IH
      { entries := { fst := fst✝, snd := snd✝ } :: l,
        nodupKeys := (_ : NodupKeys ({ fst := fst✝, snd := snd✝ } :: l)) })
    (IH { fst := fst✝, snd := snd✝ }.fst { fst := fst✝, snd := snd✝ }.snd { entries := l, nodupKeys := hl } h
      (insertRec H0 IH { entries := l, nodupKeys := hl }))
⊢ insertRec H0 IH
      (insert { fst := fst✝, snd := snd✝ }.fst { fst := fst✝, snd := snd✝ }.snd { entries := l, nodupKeys := hl }) =
    IH { fst := fst✝, snd := snd✝ }.fst { fst := fst✝, snd := snd✝ }.snd { entries := l, nodupKeys := hl } h
      (insertRec H0 IH { entries := l, nodupKeys := hl })

Next tactic:
apply eq_of_heq
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) := by
  cases' l with l hl
  suffices HEq (@insertRec α β _ C H0 IH ⟨c :: l, nodupKeys_cons.2 ⟨h, hl⟩⟩)
      (IH c.1 c.2 ⟨l, hl⟩ h (@insertRec α β _ C H0 IH ⟨l, hl⟩)) by
    cases c
    apply eq_of_heq
    

Proof state:
case mk.h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
l : List (Sigma β)
hl : NodupKeys l
fst✝ : α
snd✝ : β fst✝
h : { fst := fst✝, snd := snd✝ }.fst ∉ { entries := l, nodupKeys := hl }
this :
  HEq
    (insertRec H0 IH
      { entries := { fst := fst✝, snd := snd✝ } :: l,
        nodupKeys := (_ : NodupKeys ({ fst := fst✝, snd := snd✝ } :: l)) })
    (IH { fst := fst✝, snd := snd✝ }.fst { fst := fst✝, snd := snd✝ }.snd { entries := l, nodupKeys := hl } h
      (insertRec H0 IH { entries := l, nodupKeys := hl }))
⊢ HEq
    (insertRec H0 IH
      (insert { fst := fst✝, snd := snd✝ }.fst { fst := fst✝, snd := snd✝ }.snd { entries := l, nodupKeys := hl }))
    (IH { fst := fst✝, snd := snd✝ }.fst { fst := fst✝, snd := snd✝ }.snd { entries := l, nodupKeys := hl } h
      (insertRec H0 IH { entries := l, nodupKeys := hl }))

Next tactic:
convert this
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) := by
  cases' l with l hl
  suffices HEq (@insertRec α β _ C H0 IH ⟨c :: l, nodupKeys_cons.2 ⟨h, hl⟩⟩)
      (IH c.1 c.2 ⟨l, hl⟩ h (@insertRec α β _ C H0 IH ⟨l, hl⟩)) by
    cases c
    apply eq_of_heq
    convert this <;> 

Proof state:
case h.e'_1.h.e'_1.h.e'_3.h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
l : List (Sigma β)
hl : NodupKeys l
fst✝ : α
snd✝ : β fst✝
h : { fst := fst✝, snd := snd✝ }.fst ∉ { entries := l, nodupKeys := hl }
this :
  HEq
    (insertRec H0 IH
      { entries := { fst := fst✝, snd := snd✝ } :: l,
        nodupKeys := (_ : NodupKeys ({ fst := fst✝, snd := snd✝ } :: l)) })
    (IH { fst := fst✝, snd := snd✝ }.fst { fst := fst✝, snd := snd✝ }.snd { entries := l, nodupKeys := hl } h
      (insertRec H0 IH { entries := l, nodupKeys := hl }))
⊢ (insert { fst := fst✝, snd := snd✝ }.fst { fst := fst✝, snd := snd✝ }.snd { entries := l, nodupKeys := hl }).entries =
    { fst := fst✝, snd := snd✝ } :: l

Next tactic:
rw [insert_of_neg h]
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) := by
  cases' l with l hl
  suffices HEq (@insertRec α β _ C H0 IH ⟨c :: l, nodupKeys_cons.2 ⟨h, hl⟩⟩)
      (IH c.1 c.2 ⟨l, hl⟩ h (@insertRec α β _ C H0 IH ⟨l, hl⟩)) by
    cases c
    apply eq_of_heq
    convert this <;> 

Proof state:
case h.e'_2.e'_7.h.e'_3.h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
l : List (Sigma β)
hl : NodupKeys l
fst✝ : α
snd✝ : β fst✝
h : { fst := fst✝, snd := snd✝ }.fst ∉ { entries := l, nodupKeys := hl }
this :
  HEq
    (insertRec H0 IH
      { entries := { fst := fst✝, snd := snd✝ } :: l,
        nodupKeys := (_ : NodupKeys ({ fst := fst✝, snd := snd✝ } :: l)) })
    (IH { fst := fst✝, snd := snd✝ }.fst { fst := fst✝, snd := snd✝ }.snd { entries := l, nodupKeys := hl } h
      (insertRec H0 IH { entries := l, nodupKeys := hl }))
e_1✝ :
  C (insert { fst := fst✝, snd := snd✝ }.fst { fst := fst✝, snd := snd✝ }.snd { entries := l, nodupKeys := hl }) =
    C { entries := { fst := fst✝, snd := snd✝ } :: l, nodupKeys := (_ : NodupKeys ({ fst := fst✝, snd := snd✝ } :: l)) }
⊢ (insert { fst := fst✝, snd := snd✝ }.fst { fst := fst✝, snd := snd✝ }.snd { entries := l, nodupKeys := hl }).entries =
    { fst := fst✝, snd := snd✝ } :: l

Next tactic:
rw [insert_of_neg h]
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) := by
  cases' l with l hl
  suffices HEq (@insertRec α β _ C H0 IH ⟨c :: l, nodupKeys_cons.2 ⟨h, hl⟩⟩)
      (IH c.1 c.2 ⟨l, hl⟩ h (@insertRec α β _ C H0 IH ⟨l, hl⟩)) by
    cases c
    apply eq_of_heq
    convert this <;> rw [insert_of_neg h]
  

Proof state:
case mk
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
c : Sigma β
l : List (Sigma β)
hl : NodupKeys l
h : c.fst ∉ { entries := l, nodupKeys := hl }
⊢ HEq (insertRec H0 IH { entries := c :: l, nodupKeys := (_ : NodupKeys (c :: l)) })
    (IH c.fst c.snd { entries := l, nodupKeys := hl } h (insertRec H0 IH { entries := l, nodupKeys := hl }))

Next tactic:
rw [insertRec]
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) := by
  cases' l with l hl
  suffices HEq (@insertRec α β _ C H0 IH ⟨c :: l, nodupKeys_cons.2 ⟨h, hl⟩⟩)
      (IH c.1 c.2 ⟨l, hl⟩ h (@insertRec α β _ C H0 IH ⟨l, hl⟩)) by
    cases c
    apply eq_of_heq
    convert this <;> rw [insert_of_neg h]
  rw [insertRec]
  

Proof state:
case mk
α : Type u
β : α → Type v
inst✝ : DecidableEq α
C : AList β → Sort u_1
H0 : C ∅
IH : (a : α) → (b : β a) → (l : AList β) → a ∉ l → C l → C (insert a b l)
c : Sigma β
l : List (Sigma β)
hl : NodupKeys l
h : c.fst ∉ { entries := l, nodupKeys := hl }
⊢ HEq
    (Eq.mpr
      (_ :
        C { entries := c :: l, nodupKeys := (_ : NodupKeys (c :: l)) } =
          C (insert c.fst c.snd { entries := l, nodupKeys := (_ : NodupKeys l) }))
      (IH c.fst c.snd { entries := l, nodupKeys := (_ : NodupKeys l) }
        (_ : c.fst ∉ List.keys { entries := l, nodupKeys := (_ : NodupKeys l) }.entries)
        (insertRec H0 IH { entries := l, nodupKeys := (_ : NodupKeys l) })))
    (IH c.fst c.snd { entries := l, nodupKeys := hl } h (insertRec H0 IH { entries := l, nodupKeys := hl }))

Next tactic:
apply cast_heq
/-- Erase a key from the map, and return the corresponding value, if found. -/
def extract (a : α) (s : AList β) : Option (β a) × AList β :=
  have : (kextract a s.entries).2.NodupKeys := by
    

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s : AList β
⊢ NodupKeys (kextract a s.entries).2

Next tactic:
rw [kextract_eq_dlookup_kerase]
/-- Erase a key from the map, and return the corresponding value, if found. -/
def extract (a : α) (s : AList β) : Option (β a) × AList β :=
  have : (kextract a s.entries).2.NodupKeys := by
    rw [kextract_eq_dlookup_kerase]; 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s : AList β
⊢ NodupKeys (dlookup a s.entries, kerase a s.entries).2

Next tactic:
exact s.nodupKeys.kerase _
@[simp]
theorem extract_eq_lookup_erase (a : α) (s : AList β) : extract a s = (lookup a s, erase a s) := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s : AList β
⊢ extract a s = (lookup a s, erase a s)

Next tactic:
simp [extract]
@[simp]
theorem extract_eq_lookup_erase (a : α) (s : AList β) : extract a s = (lookup a s, erase a s) := by
  simp [extract]; 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s : AList β
⊢ dlookup a s.entries = lookup a s ∧
    { entries := kerase a s.entries, nodupKeys := (_ : NodupKeys (kerase a s.entries)) } = erase a s

Next tactic:
constructor
@[simp]
theorem extract_eq_lookup_erase (a : α) (s : AList β) : extract a s = (lookup a s, erase a s) := by
  simp [extract]; constructor <;> 

Proof state:
case left
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s : AList β
⊢ dlookup a s.entries = lookup a s

Next tactic:
rfl
@[simp]
theorem extract_eq_lookup_erase (a : α) (s : AList β) : extract a s = (lookup a s, erase a s) := by
  simp [extract]; constructor <;> 

Proof state:
case right
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
s : AList β
⊢ { entries := kerase a s.entries, nodupKeys := (_ : NodupKeys (kerase a s.entries)) } = erase a s

Next tactic:
rfl