l3lab/ntp-mathlib huggingface dataset:
set_option linter.unnecessarySimpa false in
theorem insertNth_injective (n : ℕ) (x : α) : Function.Injective (insertNth n x) := by
  induction' n with n IH
  · have : insertNth 0 x = cons x := funext fun _ => rfl
    simp [this]
  · rintro (_ | ⟨a, as⟩) (_ | ⟨b, bs⟩) h <;> 

Proof state:
case succ.cons.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a✝ x : α
n : ℕ
IH : Injective (insertNth n x)
a : α
as : List α
h : insertNth (succ n) x (a :: as) = insertNth (succ n) x []
⊢ a :: as = []

Next tactic:
simpa [IH.eq_iff] using h
set_option linter.unnecessarySimpa false in
theorem insertNth_injective (n : ℕ) (x : α) : Function.Injective (insertNth n x) := by
  induction' n with n IH
  · have : insertNth 0 x = cons x := funext fun _ => rfl
    simp [this]
  · rintro (_ | ⟨a, as⟩) (_ | ⟨b, bs⟩) h <;> 

Proof state:
case succ.cons.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a✝ x : α
n : ℕ
IH : Injective (insertNth n x)
a : α
as : List α
b : α
bs : List α
h : insertNth (succ n) x (a :: as) = insertNth (succ n) x (b :: bs)
⊢ a :: as = b :: bs

Next tactic:
simpa [IH.eq_iff] using h
theorem map_eq_foldr (f : α → β) (l : List α) : map f l = foldr (fun a bs => f a :: bs) [] l := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
l : List α
⊢ map f l = foldr (fun a bs => f a :: bs) [] l

Next tactic:
induction l
theorem map_eq_foldr (f : α → β) (l : List α) : map f l = foldr (fun a bs => f a :: bs) [] l := by
  induction l <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
⊢ map f [] = foldr (fun a bs => f a :: bs) [] []

Next tactic:
simp [*]
theorem map_eq_foldr (f : α → β) (l : List α) : map f l = foldr (fun a bs => f a :: bs) [] l := by
  induction l <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
head✝ : α
tail✝ : List α
tail_ih✝ : map f tail✝ = foldr (fun a bs => f a :: bs) [] tail✝
⊢ map f (head✝ :: tail✝) = foldr (fun a bs => f a :: bs) [] (head✝ :: tail✝)

Next tactic:
simp [*]
theorem map_congr {f g : α → β} : ∀ {l : List α}, (∀ x ∈ l, f x = g x) → map f l = map g l
  | [], _ => rfl
  | a :: l, h => by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f g : α → β
a : α
l : List α
h : ∀ (x : α), x ∈ a :: l → f x = g x
⊢ map f (a :: l) = map g (a :: l)

Next tactic:
let ⟨h₁, h₂⟩ := forall_mem_cons.1 h
theorem map_congr {f g : α → β} : ∀ {l : List α}, (∀ x ∈ l, f x = g x) → map f l = map g l
  | [], _ => rfl
  | a :: l, h => by
    let ⟨h₁, h₂⟩ := forall_mem_cons.1 h
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f g : α → β
a : α
l : List α
h : ∀ (x : α), x ∈ a :: l → f x = g x
h₁ : f a = g a
h₂ : ∀ (x : α), x ∈ l → f x = g x
⊢ map f (a :: l) = map g (a :: l)

Next tactic:
rw [map, map, h₁, map_congr h₂]
theorem map_eq_map_iff {f g : α → β} {l : List α} : map f l = map g l ↔ ∀ x ∈ l, f x = g x := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f g : α → β
l : List α
⊢ map f l = map g l ↔ ∀ (x : α), x ∈ l → f x = g x

Next tactic:
refine' ⟨_, map_congr⟩
theorem map_eq_map_iff {f g : α → β} {l : List α} : map f l = map g l ↔ ∀ x ∈ l, f x = g x := by
  refine' ⟨_, map_congr⟩; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f g : α → β
l : List α
⊢ map f l = map g l → ∀ (x : α), x ∈ l → f x = g x

Next tactic:
intro h x hx
theorem map_eq_map_iff {f g : α → β} {l : List α} : map f l = map g l ↔ ∀ x ∈ l, f x = g x := by
  refine' ⟨_, map_congr⟩; intro h x hx
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f g : α → β
l : List α
h : map f l = map g l
x : α
hx : x ∈ l
⊢ f x = g x

Next tactic:
rw [mem_iff_get] at hx
theorem map_eq_map_iff {f g : α → β} {l : List α} : map f l = map g l ↔ ∀ x ∈ l, f x = g x := by
  refine' ⟨_, map_congr⟩; intro h x hx
  rw [mem_iff_get] at hx; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f g : α → β
l : List α
h : map f l = map g l
x : α
hx : ∃ n, get l n = x
⊢ f x = g x

Next tactic:
rcases hx with ⟨n, hn, rfl⟩
theorem map_eq_map_iff {f g : α → β} {l : List α} : map f l = map g l ↔ ∀ x ∈ l, f x = g x := by
  refine' ⟨_, map_congr⟩; intro h x hx
  rw [mem_iff_get] at hx; rcases hx with ⟨n, hn, rfl⟩
  

Proof state:
case intro.refl
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f g : α → β
l : List α
h : map f l = map g l
n : Fin (length l)
⊢ f (get l n) = g (get l n)

Next tactic:
rw [get_map_rev f, get_map_rev g]
theorem map_eq_map_iff {f g : α → β} {l : List α} : map f l = map g l ↔ ∀ x ∈ l, f x = g x := by
  refine' ⟨_, map_congr⟩; intro h x hx
  rw [mem_iff_get] at hx; rcases hx with ⟨n, hn, rfl⟩
  rw [get_map_rev f, get_map_rev g]
  

Proof state:
case intro.refl
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f g : α → β
l : List α
h : map f l = map g l
n : Fin (length l)
⊢ get (map f l) { val := ↑n, isLt := (_ : ↑n < length (map f l)) } =
    get (map g l) { val := ↑n, isLt := (_ : ↑n < length (map g l)) }

Next tactic:
congr!
theorem map_concat (f : α → β) (a : α) (l : List α) :
    map f (concat l a) = concat (map f l) (f a) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
a : α
l : List α
⊢ map f (concat l a) = concat (map f l) (f a)

Next tactic:
induction l <;> [rfl; simp only [*, concat_eq_append, cons_append, map, map_append]]
theorem map_concat (f : α → β) (a : α) (l : List α) :
    map f (concat l a) = concat (map f l) (f a) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
a : α
l : List α
⊢ map f (concat l a) = concat (map f l) (f a)

Next tactic:
induction l
theorem map_concat (f : α → β) (a : α) (l : List α) :
    map f (concat l a) = concat (map f l) (f a) := by
  induction l <;> [

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
a : α
⊢ map f (concat [] a) = concat (map f []) (f a)

Next tactic:
rfl
theorem map_concat (f : α → β) (a : α) (l : List α) :
    map f (concat l a) = concat (map f l) (f a) := by
  induction l <;> [rfl; 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
a head✝ : α
tail✝ : List α
tail_ih✝ : map f (concat tail✝ a) = concat (map f tail✝) (f a)
⊢ map f (concat (head✝ :: tail✝) a) = concat (map f (head✝ :: tail✝)) (f a)

Next tactic:
simp only [*, concat_eq_append, cons_append, map, map_append]
theorem map_id'' {f : α → α} (h : ∀ x, f x = x) (l : List α) : map f l = l := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → α
h : ∀ (x : α), f x = x
l : List α
⊢ map f l = l

Next tactic:
simp [show f = id from funext h]
theorem eq_nil_of_map_eq_nil {f : α → β} {l : List α} (h : map f l = nil) : l = nil :=
  eq_nil_of_length_eq_zero <| by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
l : List α
h : map f l = []
⊢ length l = 0

Next tactic:
rw [← length_map l f, h]
theorem eq_nil_of_map_eq_nil {f : α → β} {l : List α} (h : map f l = nil) : l = nil :=
  eq_nil_of_length_eq_zero <| by rw [← length_map l f, h]; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
l : List α
h : map f l = []
⊢ length [] = 0

Next tactic:
rfl
@[simp]
theorem map_join (f : α → β) (L : List (List α)) : map f (join L) = join (map (map f) L) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
L : List (List α)
⊢ map f (join L) = join (map (map f) L)

Next tactic:
induction L <;> [rfl; simp only [*, join, map, map_append]]
@[simp]
theorem map_join (f : α → β) (L : List (List α)) : map f (join L) = join (map (map f) L) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
L : List (List α)
⊢ map f (join L) = join (map (map f) L)

Next tactic:
induction L
@[simp]
theorem map_join (f : α → β) (L : List (List α)) : map f (join L) = join (map (map f) L) := by
  induction L <;> [

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
⊢ map f (join []) = join (map (map f) [])

Next tactic:
rfl
@[simp]
theorem map_join (f : α → β) (L : List (List α)) : map f (join L) = join (map (map f) L) := by
  induction L <;> [rfl; 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
head✝ : List α
tail✝ : List (List α)
tail_ih✝ : map f (join tail✝) = join (map (map f) tail✝)
⊢ map f (join (head✝ :: tail✝)) = join (map (map f) (head✝ :: tail✝))

Next tactic:
simp only [*, join, map, map_append]
theorem bind_ret_eq_map (f : α → β) (l : List α) : l.bind (List.ret ∘ f) = map f l := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
l : List α
⊢ List.bind l (List.ret ∘ f) = map f l

Next tactic:
unfold List.bind
theorem bind_ret_eq_map (f : α → β) (l : List α) : l.bind (List.ret ∘ f) = map f l := by
  unfold List.bind
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
l : List α
⊢ join (map (List.ret ∘ f) l) = map f l

Next tactic:
induction l
theorem bind_ret_eq_map (f : α → β) (l : List α) : l.bind (List.ret ∘ f) = map f l := by
  unfold List.bind
  induction l <;>
    

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
⊢ join (map (List.ret ∘ f) []) = map f []

Next tactic:
simp (config := { unfoldPartialApp := true })
      [map, join, List.ret, cons_append, nil_append, *] at *
theorem bind_ret_eq_map (f : α → β) (l : List α) : l.bind (List.ret ∘ f) = map f l := by
  unfold List.bind
  induction l <;>
    

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
head✝ : α
tail✝ : List α
tail_ih✝ : join (map (List.ret ∘ f) tail✝) = map f tail✝
⊢ join (map (List.ret ∘ f) (head✝ :: tail✝)) = map f (head✝ :: tail✝)

Next tactic:
simp (config := { unfoldPartialApp := true })
      [map, join, List.ret, cons_append, nil_append, *] at *
theorem bind_ret_eq_map (f : α → β) (l : List α) : l.bind (List.ret ∘ f) = map f l := by
  unfold List.bind
  induction l <;>
    simp (config := { unfoldPartialApp := true })
      [map, join, List.ret, cons_append, nil_append, *] at *
  

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
head✝ : α
tail✝ : List α
tail_ih✝ : join (map ((fun a => [a]) ∘ f) tail✝) = map f tail✝
⊢ join (map ((fun a => [a]) ∘ f) tail✝) = map f tail✝

Next tactic:
assumption
@[simp]
theorem map_tail (f : α → β) (l) : map f (tail l) = tail (map f l) := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
l : List α
⊢ map f (tail l) = tail (map f l)

Next tactic:
cases l
@[simp]
theorem map_tail (f : α → β) (l) : map f (tail l) = tail (map f l) := by cases l <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
⊢ map f (tail []) = tail (map f [])

Next tactic:
rfl
@[simp]
theorem map_tail (f : α → β) (l) : map f (tail l) = tail (map f l) := by cases l <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
head✝ : α
tail✝ : List α
⊢ map f (tail (head✝ :: tail✝)) = tail (map f (head✝ :: tail✝))

Next tactic:
rfl
/-- Composing a `List.map` with another `List.map` is equal to
a single `List.map` of composed functions.
-/
@[simp]
theorem map_comp_map (g : β → γ) (f : α → β) : map g ∘ map f = map (g ∘ f) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
g : β → γ
f : α → β
⊢ map g ∘ map f = map (g ∘ f)

Next tactic:
ext l
/-- Composing a `List.map` with another `List.map` is equal to
a single `List.map` of composed functions.
-/
@[simp]
theorem map_comp_map (g : β → γ) (f : α → β) : map g ∘ map f = map (g ∘ f) := by
  ext l; 

Proof state:
case h.a.a
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
g : β → γ
f : α → β
l : List α
n✝ : ℕ
a✝ : γ
⊢ a✝ ∈ get? ((map g ∘ map f) l) n✝ ↔ a✝ ∈ get? (map (g ∘ f) l) n✝

Next tactic:
rw [comp_map, Function.comp_apply]
theorem _root_.Function.LeftInverse.list_map {f : α → β} {g : β → α} (h : LeftInverse f g) :
    LeftInverse (map f) (map g)
  | [] => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
g : β → α
h : LeftInverse f g
⊢ map f (map g []) = []

Next tactic:
simp_rw [map_nil]
theorem _root_.Function.LeftInverse.list_map {f : α → β} {g : β → α} (h : LeftInverse f g) :
    LeftInverse (map f) (map g)
  | [] => by simp_rw [map_nil]
  | x :: xs => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
g : β → α
h : LeftInverse f g
x : β
xs : List β
⊢ map f (map g (x :: xs)) = x :: xs

Next tactic:
simp_rw [map_cons, h x, h.list_map xs]
@[simp]
theorem map_leftInverse_iff {f : α → β} {g : β → α} :
    LeftInverse (map f) (map g) ↔ LeftInverse f g :=
  ⟨fun h x => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
g : β → α
h : LeftInverse (map f) (map g)
x : β
⊢ f (g x) = x

Next tactic:
injection h [x]
theorem _root_.Function.Injective.list_map {f : α → β} (h : Injective f) :
    Injective (map f)
  | [], [], _ => rfl
  | x :: xs, y :: ys, hxy => by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
h : Injective f
x : α
xs : List α
y : α
ys : List α
hxy : map f (x :: xs) = map f (y :: ys)
⊢ x :: xs = y :: ys

Next tactic:
injection hxy with hxy hxys
theorem _root_.Function.Injective.list_map {f : α → β} (h : Injective f) :
    Injective (map f)
  | [], [], _ => rfl
  | x :: xs, y :: ys, hxy => by
    injection hxy with hxy hxys
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
h : Injective f
x : α
xs : List α
y : α
ys : List α
hxy : f x = f y
hxys : map f xs = map f ys
⊢ x :: xs = y :: ys

Next tactic:
rw [h hxy, h.list_map hxys]
@[simp]
theorem map_injective_iff {f : α → β} : Injective (map f) ↔ Injective f := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
⊢ Injective (map f) ↔ Injective f

Next tactic:
refine ⟨fun h x y hxy => ?_, (·.list_map)⟩
@[simp]
theorem map_injective_iff {f : α → β} : Injective (map f) ↔ Injective f := by
  refine ⟨fun h x y hxy => ?_, (·.list_map)⟩
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
h : Injective (map f)
x y : α
hxy : f x = f y
⊢ x = y

Next tactic:
suffices [x] = [y] by simpa using this
@[simp]
theorem map_injective_iff {f : α → β} : Injective (map f) ↔ Injective f := by
  refine ⟨fun h x y hxy => ?_, (·.list_map)⟩
  suffices [x] = [y] by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
h : Injective (map f)
x y : α
hxy : f x = f y
this : [x] = [y]
⊢ x = y

Next tactic:
simpa using this
@[simp]
theorem map_injective_iff {f : α → β} : Injective (map f) ↔ Injective f := by
  refine ⟨fun h x y hxy => ?_, (·.list_map)⟩
  suffices [x] = [y] by simpa using this
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
h : Injective (map f)
x y : α
hxy : f x = f y
⊢ [x] = [y]

Next tactic:
apply h
@[simp]
theorem map_injective_iff {f : α → β} : Injective (map f) ↔ Injective f := by
  refine ⟨fun h x y hxy => ?_, (·.list_map)⟩
  suffices [x] = [y] by simpa using this
  apply h
  

Proof state:
case a
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
h : Injective (map f)
x y : α
hxy : f x = f y
⊢ map f [x] = map f [y]

Next tactic:
simp [hxy]
@[simp]
theorem map_surjective_iff {f : α → β} : Surjective (map f) ↔ Surjective f := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
⊢ Surjective (map f) ↔ Surjective f

Next tactic:
refine ⟨fun h x => ?_, (·.list_map)⟩
@[simp]
theorem map_surjective_iff {f : α → β} : Surjective (map f) ↔ Surjective f := by
  refine ⟨fun h x => ?_, (·.list_map)⟩
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
h : Surjective (map f)
x : β
⊢ ∃ a, f a = x

Next tactic:
let ⟨[y], hxy⟩ := h [x]
@[simp]
theorem map_surjective_iff {f : α → β} : Surjective (map f) ↔ Surjective f := by
  refine ⟨fun h x => ?_, (·.list_map)⟩
  let ⟨[y], hxy⟩ := h [x]
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
h : Surjective (map f)
x : β
y : α
hxy : map f [y] = [x]
⊢ ∃ a, f a = x

Next tactic:
exact ⟨_, List.singleton_injective hxy⟩
@[simp]
theorem map_bijective_iff {f : α → β} : Bijective (map f) ↔ Bijective f := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
⊢ Bijective (map f) ↔ Bijective f

Next tactic:
simp_rw [Function.Bijective, map_injective_iff, map_surjective_iff]
theorem map_filter_eq_foldr (f : α → β) (p : α → Bool) (as : List α) :
    map f (filter p as) = foldr (fun a bs => bif p a then f a :: bs else bs) [] as := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
p : α → Bool
as : List α
⊢ map f (filter p as) = foldr (fun a bs => bif p a then f a :: bs else bs) [] as

Next tactic:
induction' as with head tail
theorem map_filter_eq_foldr (f : α → β) (p : α → Bool) (as : List α) :
    map f (filter p as) = foldr (fun a bs => bif p a then f a :: bs else bs) [] as := by
  induction' as with head tail
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
p : α → Bool
⊢ map f (filter p []) = foldr (fun a bs => bif p a then f a :: bs else bs) [] []

Next tactic:
rfl
theorem map_filter_eq_foldr (f : α → β) (p : α → Bool) (as : List α) :
    map f (filter p as) = foldr (fun a bs => bif p a then f a :: bs else bs) [] as := by
  induction' as with head tail
  · rfl
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
p : α → Bool
head : α
tail : List α
tail_ih✝ : map f (filter p tail) = foldr (fun a bs => bif p a then f a :: bs else bs) [] tail
⊢ map f (filter p (head :: tail)) = foldr (fun a bs => bif p a then f a :: bs else bs) [] (head :: tail)

Next tactic:
simp only [foldr]
theorem map_filter_eq_foldr (f : α → β) (p : α → Bool) (as : List α) :
    map f (filter p as) = foldr (fun a bs => bif p a then f a :: bs else bs) [] as := by
  induction' as with head tail
  · rfl
  · simp only [foldr]
    

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
p : α → Bool
head : α
tail : List α
tail_ih✝ : map f (filter p tail) = foldr (fun a bs => bif p a then f a :: bs else bs) [] tail
⊢ map f (filter p (head :: tail)) =
    bif p head then f head :: foldr (fun a bs => bif p a then f a :: bs else bs) [] tail
    else foldr (fun a bs => bif p a then f a :: bs else bs) [] tail

Next tactic:
cases hp : p head
theorem map_filter_eq_foldr (f : α → β) (p : α → Bool) (as : List α) :
    map f (filter p as) = foldr (fun a bs => bif p a then f a :: bs else bs) [] as := by
  induction' as with head tail
  · rfl
  · simp only [foldr]
    cases hp : p head <;> 

Proof state:
case cons.false
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
p : α → Bool
head : α
tail : List α
tail_ih✝ : map f (filter p tail) = foldr (fun a bs => bif p a then f a :: bs else bs) [] tail
hp : p head = false
⊢ map f (filter p (head :: tail)) =
    bif false then f head :: foldr (fun a bs => bif p a then f a :: bs else bs) [] tail
    else foldr (fun a bs => bif p a then f a :: bs else bs) [] tail

Next tactic:
simp [filter, *]
theorem map_filter_eq_foldr (f : α → β) (p : α → Bool) (as : List α) :
    map f (filter p as) = foldr (fun a bs => bif p a then f a :: bs else bs) [] as := by
  induction' as with head tail
  · rfl
  · simp only [foldr]
    cases hp : p head <;> 

Proof state:
case cons.true
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
p : α → Bool
head : α
tail : List α
tail_ih✝ : map f (filter p tail) = foldr (fun a bs => bif p a then f a :: bs else bs) [] tail
hp : p head = true
⊢ map f (filter p (head :: tail)) =
    bif true then f head :: foldr (fun a bs => bif p a then f a :: bs else bs) [] tail
    else foldr (fun a bs => bif p a then f a :: bs else bs) [] tail

Next tactic:
simp [filter, *]
theorem getLast_map (f : α → β) {l : List α} (hl : l ≠ []) :
    (l.map f).getLast (mt eq_nil_of_map_eq_nil hl) = f (l.getLast hl) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
l : List α
hl : l ≠ []
⊢ getLast (map f l) (_ : ¬map f l = []) = f (getLast l hl)

Next tactic:
induction' l with l_hd l_tl l_ih
theorem getLast_map (f : α → β) {l : List α} (hl : l ≠ []) :
    (l.map f).getLast (mt eq_nil_of_map_eq_nil hl) = f (l.getLast hl) := by
  induction' l with l_hd l_tl l_ih
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
hl : [] ≠ []
⊢ getLast (map f []) (_ : ¬map f [] = []) = f (getLast [] hl)

Next tactic:
apply (hl rfl).elim
theorem getLast_map (f : α → β) {l : List α} (hl : l ≠ []) :
    (l.map f).getLast (mt eq_nil_of_map_eq_nil hl) = f (l.getLast hl) := by
  induction' l with l_hd l_tl l_ih
  · apply (hl rfl).elim
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
l_hd : α
l_tl : List α
l_ih : ∀ (hl : l_tl ≠ []), getLast (map f l_tl) (_ : ¬map f l_tl = []) = f (getLast l_tl hl)
hl : l_hd :: l_tl ≠ []
⊢ getLast (map f (l_hd :: l_tl)) (_ : ¬map f (l_hd :: l_tl) = []) = f (getLast (l_hd :: l_tl) hl)

Next tactic:
cases l_tl
theorem getLast_map (f : α → β) {l : List α} (hl : l ≠ []) :
    (l.map f).getLast (mt eq_nil_of_map_eq_nil hl) = f (l.getLast hl) := by
  induction' l with l_hd l_tl l_ih
  · apply (hl rfl).elim
  · cases l_tl
    · 

Proof state:
case cons.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
l_hd : α
l_ih : ∀ (hl : [] ≠ []), getLast (map f []) (_ : ¬map f [] = []) = f (getLast [] hl)
hl : [l_hd] ≠ []
⊢ getLast (map f [l_hd]) (_ : ¬map f [l_hd] = []) = f (getLast [l_hd] hl)

Next tactic:
simp
theorem getLast_map (f : α → β) {l : List α} (hl : l ≠ []) :
    (l.map f).getLast (mt eq_nil_of_map_eq_nil hl) = f (l.getLast hl) := by
  induction' l with l_hd l_tl l_ih
  · apply (hl rfl).elim
  · cases l_tl
    · simp
    · 

Proof state:
case cons.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
l_hd head✝ : α
tail✝ : List α
l_ih :
  ∀ (hl : head✝ :: tail✝ ≠ []),
    getLast (map f (head✝ :: tail✝)) (_ : ¬map f (head✝ :: tail✝) = []) = f (getLast (head✝ :: tail✝) hl)
hl : l_hd :: head✝ :: tail✝ ≠ []
⊢ getLast (map f (l_hd :: head✝ :: tail✝)) (_ : ¬map f (l_hd :: head✝ :: tail✝) = []) =
    f (getLast (l_hd :: head✝ :: tail✝) hl)

Next tactic:
simpa using l_ih _
theorem map_eq_replicate_iff {l : List α} {f : α → β} {b : β} :
    l.map f = replicate l.length b ↔ ∀ x ∈ l, f x = b := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
f : α → β
b : β
⊢ map f l = replicate (length l) b ↔ ∀ (x : α), x ∈ l → f x = b

Next tactic:
simp [eq_replicate]
theorem eq_of_mem_map_const {b₁ b₂ : β} {l : List α} (h : b₁ ∈ map (const α b₂) l) :
    b₁ = b₂ := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
b₁ b₂ : β
l : List α
h : b₁ ∈ map (const α b₂) l
⊢ b₁ = b₂

Next tactic:
rw [map_const] at h
theorem eq_of_mem_map_const {b₁ b₂ : β} {l : List α} (h : b₁ ∈ map (const α b₂) l) :
    b₁ = b₂ := by rw [map_const] at h; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
b₁ b₂ : β
l : List α
h : b₁ ∈ replicate (length l) b₂
⊢ b₁ = b₂

Next tactic:
exact eq_of_mem_replicate h
theorem nil_zipWith (f : α → β → γ) (l : List β) : zipWith f [] l = [] := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β → γ
l : List β
⊢ zipWith f [] l = []

Next tactic:
cases l
theorem nil_zipWith (f : α → β → γ) (l : List β) : zipWith f [] l = [] := by cases l <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β → γ
⊢ zipWith f [] [] = []

Next tactic:
rfl