l3lab/ntp-mathlib huggingface dataset:
theorem injOn_insertNth_index_of_not_mem (l : List α) (x : α) (hx : x ∉ l) :
    Set.InjOn (fun k => insertNth k x l) { n | n ≤ l.length } := by
  induction' l with hd tl IH
  · intro n hn m hm _
    simp only [Set.mem_singleton_iff, Set.setOf_eq_eq_singleton,
      length, nonpos_iff_eq_zero] at hn hm
    simp [hn, hm]
  · intro n hn m hm h
    simp only [length, Set.mem_setOf_eq] at hn hm
    simp only [mem_cons, not_or] at hx
    cases n <;> cases m
    · rfl
    · 

Proof state:
case cons.zero.succ
α : Type u_1
β : Type u_2
γ : Type u_3
x hd : α
tl : List α
IH : x ∉ tl → Set.InjOn (fun k => insertNth k x tl) {n | n ≤ length tl}
hx : ¬x = hd ∧ x ∉ tl
hn : Nat.zero ≤ length tl + 1
n✝ : ℕ
hm : Nat.succ n✝ ≤ length tl + 1
h : (fun k => insertNth k x (hd :: tl)) Nat.zero = (fun k => insertNth k x (hd :: tl)) (Nat.succ n✝)
⊢ Nat.zero = Nat.succ n✝

Next tactic:
simp [hx.left] at h
theorem injOn_insertNth_index_of_not_mem (l : List α) (x : α) (hx : x ∉ l) :
    Set.InjOn (fun k => insertNth k x l) { n | n ≤ l.length } := by
  induction' l with hd tl IH
  · intro n hn m hm _
    simp only [Set.mem_singleton_iff, Set.setOf_eq_eq_singleton,
      length, nonpos_iff_eq_zero] at hn hm
    simp [hn, hm]
  · intro n hn m hm h
    simp only [length, Set.mem_setOf_eq] at hn hm
    simp only [mem_cons, not_or] at hx
    cases n <;> cases m
    · rfl
    · simp [hx.left] at h
    · 

Proof state:
case cons.succ.zero
α : Type u_1
β : Type u_2
γ : Type u_3
x hd : α
tl : List α
IH : x ∉ tl → Set.InjOn (fun k => insertNth k x tl) {n | n ≤ length tl}
hx : ¬x = hd ∧ x ∉ tl
n✝ : ℕ
hn : Nat.succ n✝ ≤ length tl + 1
hm : Nat.zero ≤ length tl + 1
h : (fun k => insertNth k x (hd :: tl)) (Nat.succ n✝) = (fun k => insertNth k x (hd :: tl)) Nat.zero
⊢ Nat.succ n✝ = Nat.zero

Next tactic:
simp [Ne.symm hx.left] at h
theorem injOn_insertNth_index_of_not_mem (l : List α) (x : α) (hx : x ∉ l) :
    Set.InjOn (fun k => insertNth k x l) { n | n ≤ l.length } := by
  induction' l with hd tl IH
  · intro n hn m hm _
    simp only [Set.mem_singleton_iff, Set.setOf_eq_eq_singleton,
      length, nonpos_iff_eq_zero] at hn hm
    simp [hn, hm]
  · intro n hn m hm h
    simp only [length, Set.mem_setOf_eq] at hn hm
    simp only [mem_cons, not_or] at hx
    cases n <;> cases m
    · rfl
    · simp [hx.left] at h
    · simp [Ne.symm hx.left] at h
    · 

Proof state:
case cons.succ.succ
α : Type u_1
β : Type u_2
γ : Type u_3
x hd : α
tl : List α
IH : x ∉ tl → Set.InjOn (fun k => insertNth k x tl) {n | n ≤ length tl}
hx : ¬x = hd ∧ x ∉ tl
n✝¹ : ℕ
hn : Nat.succ n✝¹ ≤ length tl + 1
n✝ : ℕ
hm : Nat.succ n✝ ≤ length tl + 1
h : (fun k => insertNth k x (hd :: tl)) (Nat.succ n✝¹) = (fun k => insertNth k x (hd :: tl)) (Nat.succ n✝)
⊢ Nat.succ n✝¹ = Nat.succ n✝

Next tactic:
simp only [true_and_iff, eq_self_iff_true, insertNth_succ_cons] at h
theorem injOn_insertNth_index_of_not_mem (l : List α) (x : α) (hx : x ∉ l) :
    Set.InjOn (fun k => insertNth k x l) { n | n ≤ l.length } := by
  induction' l with hd tl IH
  · intro n hn m hm _
    simp only [Set.mem_singleton_iff, Set.setOf_eq_eq_singleton,
      length, nonpos_iff_eq_zero] at hn hm
    simp [hn, hm]
  · intro n hn m hm h
    simp only [length, Set.mem_setOf_eq] at hn hm
    simp only [mem_cons, not_or] at hx
    cases n <;> cases m
    · rfl
    · simp [hx.left] at h
    · simp [Ne.symm hx.left] at h
    · simp only [true_and_iff, eq_self_iff_true, insertNth_succ_cons] at h
      

Proof state:
case cons.succ.succ
α : Type u_1
β : Type u_2
γ : Type u_3
x hd : α
tl : List α
IH : x ∉ tl → Set.InjOn (fun k => insertNth k x tl) {n | n ≤ length tl}
hx : ¬x = hd ∧ x ∉ tl
n✝¹ : ℕ
hn : Nat.succ n✝¹ ≤ length tl + 1
n✝ : ℕ
hm : Nat.succ n✝ ≤ length tl + 1
h : hd :: insertNth n✝¹ x tl = hd :: insertNth n✝ x tl
⊢ Nat.succ n✝¹ = Nat.succ n✝

Next tactic:
rw [Nat.succ_inj']
theorem injOn_insertNth_index_of_not_mem (l : List α) (x : α) (hx : x ∉ l) :
    Set.InjOn (fun k => insertNth k x l) { n | n ≤ l.length } := by
  induction' l with hd tl IH
  · intro n hn m hm _
    simp only [Set.mem_singleton_iff, Set.setOf_eq_eq_singleton,
      length, nonpos_iff_eq_zero] at hn hm
    simp [hn, hm]
  · intro n hn m hm h
    simp only [length, Set.mem_setOf_eq] at hn hm
    simp only [mem_cons, not_or] at hx
    cases n <;> cases m
    · rfl
    · simp [hx.left] at h
    · simp [Ne.symm hx.left] at h
    · simp only [true_and_iff, eq_self_iff_true, insertNth_succ_cons] at h
      rw [Nat.succ_inj']
      

Proof state:
case cons.succ.succ
α : Type u_1
β : Type u_2
γ : Type u_3
x hd : α
tl : List α
IH : x ∉ tl → Set.InjOn (fun k => insertNth k x tl) {n | n ≤ length tl}
hx : ¬x = hd ∧ x ∉ tl
n✝¹ : ℕ
hn : Nat.succ n✝¹ ≤ length tl + 1
n✝ : ℕ
hm : Nat.succ n✝ ≤ length tl + 1
h : hd :: insertNth n✝¹ x tl = hd :: insertNth n✝ x tl
⊢ n✝¹ = n✝

Next tactic:
refine' IH hx.right _ _ (by injection h)
theorem injOn_insertNth_index_of_not_mem (l : List α) (x : α) (hx : x ∉ l) :
    Set.InjOn (fun k => insertNth k x l) { n | n ≤ l.length } := by
  induction' l with hd tl IH
  · intro n hn m hm _
    simp only [Set.mem_singleton_iff, Set.setOf_eq_eq_singleton,
      length, nonpos_iff_eq_zero] at hn hm
    simp [hn, hm]
  · intro n hn m hm h
    simp only [length, Set.mem_setOf_eq] at hn hm
    simp only [mem_cons, not_or] at hx
    cases n <;> cases m
    · rfl
    · simp [hx.left] at h
    · simp [Ne.symm hx.left] at h
    · simp only [true_and_iff, eq_self_iff_true, insertNth_succ_cons] at h
      rw [Nat.succ_inj']
      refine' IH hx.right _ _ (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
x hd : α
tl : List α
IH : x ∉ tl → Set.InjOn (fun k => insertNth k x tl) {n | n ≤ length tl}
hx : ¬x = hd ∧ x ∉ tl
n✝¹ : ℕ
hn : Nat.succ n✝¹ ≤ length tl + 1
n✝ : ℕ
hm : Nat.succ n✝ ≤ length tl + 1
h : hd :: insertNth n✝¹ x tl = hd :: insertNth n✝ x tl
⊢ (fun k => insertNth k x tl) n✝¹ = (fun k => insertNth k x tl) n✝

Next tactic:
injection h
theorem injOn_insertNth_index_of_not_mem (l : List α) (x : α) (hx : x ∉ l) :
    Set.InjOn (fun k => insertNth k x l) { n | n ≤ l.length } := by
  induction' l with hd tl IH
  · intro n hn m hm _
    simp only [Set.mem_singleton_iff, Set.setOf_eq_eq_singleton,
      length, nonpos_iff_eq_zero] at hn hm
    simp [hn, hm]
  · intro n hn m hm h
    simp only [length, Set.mem_setOf_eq] at hn hm
    simp only [mem_cons, not_or] at hx
    cases n <;> cases m
    · rfl
    · simp [hx.left] at h
    · simp [Ne.symm hx.left] at h
    · simp only [true_and_iff, eq_self_iff_true, insertNth_succ_cons] at h
      rw [Nat.succ_inj']
      refine' IH hx.right _ _ (by injection h)
      · 

Proof state:
case cons.succ.succ.refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
x hd : α
tl : List α
IH : x ∉ tl → Set.InjOn (fun k => insertNth k x tl) {n | n ≤ length tl}
hx : ¬x = hd ∧ x ∉ tl
n✝¹ : ℕ
hn : Nat.succ n✝¹ ≤ length tl + 1
n✝ : ℕ
hm : Nat.succ n✝ ≤ length tl + 1
h : hd :: insertNth n✝¹ x tl = hd :: insertNth n✝ x tl
⊢ n✝¹ ∈ {n | n ≤ length tl}

Next tactic:
simpa [Nat.succ_le_succ_iff] using hn
theorem injOn_insertNth_index_of_not_mem (l : List α) (x : α) (hx : x ∉ l) :
    Set.InjOn (fun k => insertNth k x l) { n | n ≤ l.length } := by
  induction' l with hd tl IH
  · intro n hn m hm _
    simp only [Set.mem_singleton_iff, Set.setOf_eq_eq_singleton,
      length, nonpos_iff_eq_zero] at hn hm
    simp [hn, hm]
  · intro n hn m hm h
    simp only [length, Set.mem_setOf_eq] at hn hm
    simp only [mem_cons, not_or] at hx
    cases n <;> cases m
    · rfl
    · simp [hx.left] at h
    · simp [Ne.symm hx.left] at h
    · simp only [true_and_iff, eq_self_iff_true, insertNth_succ_cons] at h
      rw [Nat.succ_inj']
      refine' IH hx.right _ _ (by injection h)
      · simpa [Nat.succ_le_succ_iff] using hn
      · 

Proof state:
case cons.succ.succ.refine'_2
α : Type u_1
β : Type u_2
γ : Type u_3
x hd : α
tl : List α
IH : x ∉ tl → Set.InjOn (fun k => insertNth k x tl) {n | n ≤ length tl}
hx : ¬x = hd ∧ x ∉ tl
n✝¹ : ℕ
hn : Nat.succ n✝¹ ≤ length tl + 1
n✝ : ℕ
hm : Nat.succ n✝ ≤ length tl + 1
h : hd :: insertNth n✝¹ x tl = hd :: insertNth n✝ x tl
⊢ n✝ ∈ {n | n ≤ length tl}

Next tactic:
simpa [Nat.succ_le_succ_iff] using hm
theorem foldr_range_subset_of_range_subset {f : β → α → α} {g : γ → α → α}
    (hfg : Set.range f ⊆ Set.range g) (a : α) : Set.range (foldr f a) ⊆ Set.range (foldr g a) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : β → α → α
g : γ → α → α
hfg : Set.range f ⊆ Set.range g
a : α
⊢ Set.range (foldr f a) ⊆ Set.range (foldr g a)

Next tactic:
rintro _ ⟨l, rfl⟩
theorem foldr_range_subset_of_range_subset {f : β → α → α} {g : γ → α → α}
    (hfg : Set.range f ⊆ Set.range g) (a : α) : Set.range (foldr f a) ⊆ Set.range (foldr g a) := by
  rintro _ ⟨l, rfl⟩
  

Proof state:
case intro
α : Type u_1
β : Type u_2
γ : Type u_3
f : β → α → α
g : γ → α → α
hfg : Set.range f ⊆ Set.range g
a : α
l : List β
⊢ foldr f a l ∈ Set.range (foldr g a)

Next tactic:
induction' l with b l H
theorem foldr_range_subset_of_range_subset {f : β → α → α} {g : γ → α → α}
    (hfg : Set.range f ⊆ Set.range g) (a : α) : Set.range (foldr f a) ⊆ Set.range (foldr g a) := by
  rintro _ ⟨l, rfl⟩
  induction' l with b l H
  · 

Proof state:
case intro.nil
α : Type u_1
β : Type u_2
γ : Type u_3
f : β → α → α
g : γ → α → α
hfg : Set.range f ⊆ Set.range g
a : α
⊢ foldr f a [] ∈ Set.range (foldr g a)

Next tactic:
exact ⟨[], rfl⟩
theorem foldr_range_subset_of_range_subset {f : β → α → α} {g : γ → α → α}
    (hfg : Set.range f ⊆ Set.range g) (a : α) : Set.range (foldr f a) ⊆ Set.range (foldr g a) := by
  rintro _ ⟨l, rfl⟩
  induction' l with b l H
  · exact ⟨[], rfl⟩
  · 

Proof state:
case intro.cons
α : Type u_1
β : Type u_2
γ : Type u_3
f : β → α → α
g : γ → α → α
hfg : Set.range f ⊆ Set.range g
a : α
b : β
l : List β
H : foldr f a l ∈ Set.range (foldr g a)
⊢ foldr f a (b :: l) ∈ Set.range (foldr g a)

Next tactic:
cases' hfg (Set.mem_range_self b) with c hgf
theorem foldr_range_subset_of_range_subset {f : β → α → α} {g : γ → α → α}
    (hfg : Set.range f ⊆ Set.range g) (a : α) : Set.range (foldr f a) ⊆ Set.range (foldr g a) := by
  rintro _ ⟨l, rfl⟩
  induction' l with b l H
  · exact ⟨[], rfl⟩
  · cases' hfg (Set.mem_range_self b) with c hgf
    

Proof state:
case intro.cons.intro
α : Type u_1
β : Type u_2
γ : Type u_3
f : β → α → α
g : γ → α → α
hfg : Set.range f ⊆ Set.range g
a : α
b : β
l : List β
H : foldr f a l ∈ Set.range (foldr g a)
c : γ
hgf : g c = f b
⊢ foldr f a (b :: l) ∈ Set.range (foldr g a)

Next tactic:
cases' H with m hgf'
theorem foldr_range_subset_of_range_subset {f : β → α → α} {g : γ → α → α}
    (hfg : Set.range f ⊆ Set.range g) (a : α) : Set.range (foldr f a) ⊆ Set.range (foldr g a) := by
  rintro _ ⟨l, rfl⟩
  induction' l with b l H
  · exact ⟨[], rfl⟩
  · cases' hfg (Set.mem_range_self b) with c hgf
    cases' H with m hgf'
    

Proof state:
case intro.cons.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
f : β → α → α
g : γ → α → α
hfg : Set.range f ⊆ Set.range g
a : α
b : β
l : List β
c : γ
hgf : g c = f b
m : List γ
hgf' : foldr g a m = foldr f a l
⊢ foldr f a (b :: l) ∈ Set.range (foldr g a)

Next tactic:
rw [foldr_cons, ← hgf, ← hgf']
theorem foldr_range_subset_of_range_subset {f : β → α → α} {g : γ → α → α}
    (hfg : Set.range f ⊆ Set.range g) (a : α) : Set.range (foldr f a) ⊆ Set.range (foldr g a) := by
  rintro _ ⟨l, rfl⟩
  induction' l with b l H
  · exact ⟨[], rfl⟩
  · cases' hfg (Set.mem_range_self b) with c hgf
    cases' H with m hgf'
    rw [foldr_cons, ← hgf, ← hgf']
    

Proof state:
case intro.cons.intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
f : β → α → α
g : γ → α → α
hfg : Set.range f ⊆ Set.range g
a : α
b : β
l : List β
c : γ
hgf : g c = f b
m : List γ
hgf' : foldr g a m = foldr f a l
⊢ g c (foldr g a m) ∈ Set.range (foldr g a)

Next tactic:
exact ⟨c :: m, rfl⟩
theorem foldl_range_subset_of_range_subset {f : α → β → α} {g : α → γ → α}
    (hfg : (Set.range fun a c => f c a) ⊆ Set.range fun b c => g c b) (a : α) :
    Set.range (foldl f a) ⊆ Set.range (foldl g a) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → α
g : α → γ → α
hfg : (Set.range fun a c => f c a) ⊆ Set.range fun b c => g c b
a : α
⊢ Set.range (foldl f a) ⊆ Set.range (foldl g a)

Next tactic:
change (Set.range fun l => _) ⊆ Set.range fun l => _
theorem foldl_range_subset_of_range_subset {f : α → β → α} {g : α → γ → α}
    (hfg : (Set.range fun a c => f c a) ⊆ Set.range fun b c => g c b) (a : α) :
    Set.range (foldl f a) ⊆ Set.range (foldl g a) := by
  change (Set.range fun l => _) ⊆ Set.range fun l => _
  -- Porting note: This was simply `simp_rw [← foldr_reverse]`
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → α
g : α → γ → α
hfg : (Set.range fun a c => f c a) ⊆ Set.range fun b c => g c b
a : α
⊢ (Set.range fun l => foldl f a l) ⊆ Set.range fun l => foldl g a l

Next tactic:
simp_rw [← foldr_reverse _ (fun z w => g w z), ← foldr_reverse _ (fun z w => f w z)]
theorem foldl_range_subset_of_range_subset {f : α → β → α} {g : α → γ → α}
    (hfg : (Set.range fun a c => f c a) ⊆ Set.range fun b c => g c b) (a : α) :
    Set.range (foldl f a) ⊆ Set.range (foldl g a) := by
  change (Set.range fun l => _) ⊆ Set.range fun l => _
  -- Porting note: This was simply `simp_rw [← foldr_reverse]`
  simp_rw [← foldr_reverse _ (fun z w => g w z), ← foldr_reverse _ (fun z w => f w z)]
  -- Porting note: This `change` was not necessary in mathlib3
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → α
g : α → γ → α
hfg : (Set.range fun a c => f c a) ⊆ Set.range fun b c => g c b
a : α
⊢ (Set.range fun l => foldr (fun z w => f w z) a (reverse l)) ⊆
    Set.range fun l => foldr (fun z w => g w z) a (reverse l)

Next tactic:
change (Set.range (foldr (fun z w => f w z) a ∘ reverse)) ⊆
    Set.range (foldr (fun z w => g w z) a ∘ reverse)
theorem foldl_range_subset_of_range_subset {f : α → β → α} {g : α → γ → α}
    (hfg : (Set.range fun a c => f c a) ⊆ Set.range fun b c => g c b) (a : α) :
    Set.range (foldl f a) ⊆ Set.range (foldl g a) := by
  change (Set.range fun l => _) ⊆ Set.range fun l => _
  -- Porting note: This was simply `simp_rw [← foldr_reverse]`
  simp_rw [← foldr_reverse _ (fun z w => g w z), ← foldr_reverse _ (fun z w => f w z)]
  -- Porting note: This `change` was not necessary in mathlib3
  change (Set.range (foldr (fun z w => f w z) a ∘ reverse)) ⊆
    Set.range (foldr (fun z w => g w z) a ∘ reverse)
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → α
g : α → γ → α
hfg : (Set.range fun a c => f c a) ⊆ Set.range fun b c => g c b
a : α
⊢ Set.range (foldr (fun z w => f w z) a ∘ reverse) ⊆ Set.range (foldr (fun z w => g w z) a ∘ reverse)

Next tactic:
simp_rw [Set.range_comp _ reverse, reverse_involutive.bijective.surjective.range_eq,
    Set.image_univ]
theorem foldl_range_subset_of_range_subset {f : α → β → α} {g : α → γ → α}
    (hfg : (Set.range fun a c => f c a) ⊆ Set.range fun b c => g c b) (a : α) :
    Set.range (foldl f a) ⊆ Set.range (foldl g a) := by
  change (Set.range fun l => _) ⊆ Set.range fun l => _
  -- Porting note: This was simply `simp_rw [← foldr_reverse]`
  simp_rw [← foldr_reverse _ (fun z w => g w z), ← foldr_reverse _ (fun z w => f w z)]
  -- Porting note: This `change` was not necessary in mathlib3
  change (Set.range (foldr (fun z w => f w z) a ∘ reverse)) ⊆
    Set.range (foldr (fun z w => g w z) a ∘ reverse)
  simp_rw [Set.range_comp _ reverse, reverse_involutive.bijective.surjective.range_eq,
    Set.image_univ]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → α
g : α → γ → α
hfg : (Set.range fun a c => f c a) ⊆ Set.range fun b c => g c b
a : α
⊢ Set.range (foldr (fun z w => f w z) a) ⊆ Set.range (foldr (fun z w => g w z) a)

Next tactic:
exact foldr_range_subset_of_range_subset hfg a
theorem mapAccumr_eq_foldr (f : α → σ → σ × β) : ∀ (as : List α) (s : σ),
    mapAccumr f as s = List.foldr (fun a s =>
                                    let r := f a s.1
                                    (r.1, r.2 :: s.2)
                                  ) (s, []) as
  | [], s => rfl
  | a :: as, s => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
f : α → σ → σ × β
a : α
as : List α
s : σ
⊢ mapAccumr f (a :: as) s =
    foldr
      (fun a s =>
        let r := f a s.1;
        (r.1, r.2 :: s.2))
      (s, []) (a :: as)

Next tactic:
simp only [mapAccumr, foldr, mapAccumr_eq_foldr f as]
theorem mapAccumr₂_eq_foldr (f : α → β → σ → σ × φ) :
    ∀ (as : List α) (bs : List β) (s : σ),
    mapAccumr₂ f as bs s = foldr (fun ab s =>
                              let r := f ab.1 ab.2 s.1
                              (r.1, r.2 :: s.2)
                            ) (s, []) (as.zip bs)
  | [], [], s => rfl
  | a :: as, [], s => rfl
  | [], b :: bs, s => rfl
  | a :: as, b :: bs, s => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
φ : Type u_5
f : α → β → σ → σ × φ
a : α
as : List α
b : β
bs : List β
s : σ
⊢ mapAccumr₂ f (a :: as) (b :: bs) s =
    foldr
      (fun ab s =>
        let r := f ab.1 ab.2 s.1;
        (r.1, r.2 :: s.2))
      (s, []) (zip (a :: as) (b :: bs))

Next tactic:
simp only [mapAccumr₂, foldr, mapAccumr₂_eq_foldr f as]
theorem mapAccumr₂_eq_foldr (f : α → β → σ → σ × φ) :
    ∀ (as : List α) (bs : List β) (s : σ),
    mapAccumr₂ f as bs s = foldr (fun ab s =>
                              let r := f ab.1 ab.2 s.1
                              (r.1, r.2 :: s.2)
                            ) (s, []) (as.zip bs)
  | [], [], s => rfl
  | a :: as, [], s => rfl
  | [], b :: bs, s => rfl
  | a :: as, b :: bs, s => by
    simp only [mapAccumr₂, foldr, mapAccumr₂_eq_foldr f as]
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
σ : Type u_4
φ : Type u_5
f : α → β → σ → σ × φ
a : α
as : List α
b : β
bs : List β
s : σ
⊢ ((f a b (foldr (fun ab s => ((f ab.1 ab.2 s.1).1, (f ab.1 ab.2 s.1).2 :: s.2)) (s, []) (zip as bs)).1).1,
      (f a b (foldr (fun ab s => ((f ab.1 ab.2 s.1).1, (f ab.1 ab.2 s.1).2 :: s.2)) (s, []) (zip as bs)).1).2 ::
        (foldr (fun ab s => ((f ab.1 ab.2 s.1).1, (f ab.1 ab.2 s.1).2 :: s.2)) (s, []) (zip as bs)).2) =
    ((f a b
          (foldr (fun ab s => ((f ab.1 ab.2 s.1).1, (f ab.1 ab.2 s.1).2 :: s.2)) (s, []) (zipWith Prod.mk as bs)).1).1,
      (f a b
            (foldr (fun ab s => ((f ab.1 ab.2 s.1).1, (f ab.1 ab.2 s.1).2 :: s.2)) (s, [])
                (zipWith Prod.mk as bs)).1).2 ::
        (foldr (fun ab s => ((f ab.1 ab.2 s.1).1, (f ab.1 ab.2 s.1).2 :: s.2)) (s, []) (zipWith Prod.mk as bs)).2)

Next tactic:
rfl
/-- A small category with products is a thin category.

in Lean, a preorder category is one where the morphisms are in Prop, which is weaker than the usual
notion of a preorder/thin category which says that each homset is subsingleton; we show the latter
rather than providing a `Preorder C` instance.
-/
instance (priority := 100) : Quiver.IsThin C := fun X Y =>
  ⟨fun r s => by
    

Proof state:
C : Type u
inst✝¹ : SmallCategory C
inst✝ : HasProducts C
X Y : C
r s : X ⟶ Y
⊢ r = s

Next tactic:
classical
      by_contra r_ne_s
      have z : (2 : Cardinal) ≤ #(X ⟶ Y) := by
        rw [Cardinal.two_le_iff]
        exact ⟨_, _, r_ne_s⟩
      let md := ΣZ W : C, Z ⟶ W
      let α := #md
      apply not_le_of_lt (Cardinal.cantor α)
      let yp : C := ∏ fun _ : md => Y
      refine' _root_.trans _ _
      · exact #(X ⟶ yp)
      · apply le_trans (Cardinal.power_le_power_right z)
        rw [Cardinal.power_def]
        apply le_of_eq
        rw [Cardinal.eq]
        refine' ⟨⟨Pi.lift, fun f k => f ≫ Pi.π _ k, _, _⟩⟩
        · intro f
          ext k
          simp
        · intro f
          ext ⟨j⟩
          simp
      · apply Cardinal.mk_le_of_injective _
        · intro f
          exact ⟨_, _, f⟩
        · rintro f g k
          cases k
          rfl
/-- A small category with products is a thin category.

in Lean, a preorder category is one where the morphisms are in Prop, which is weaker than the usual
notion of a preorder/thin category which says that each homset is subsingleton; we show the latter
rather than providing a `Preorder C` instance.
-/
instance (priority := 100) : Quiver.IsThin C := fun X Y =>
  ⟨fun r s => by
    classical
      

Proof state:
C : Type u
inst✝¹ : SmallCategory C
inst✝ : HasProducts C
X Y : C
r s : X ⟶ Y
⊢ r = s

Next tactic:
by_contra r_ne_s
/-- A small category with products is a thin category.

in Lean, a preorder category is one where the morphisms are in Prop, which is weaker than the usual
notion of a preorder/thin category which says that each homset is subsingleton; we show the latter
rather than providing a `Preorder C` instance.
-/
instance (priority := 100) : Quiver.IsThin C := fun X Y =>
  ⟨fun r s => by
    classical
      by_contra r_ne_s
      

Proof state:
C : Type u
inst✝¹ : SmallCategory C
inst✝ : HasProducts C
X Y : C
r s : X ⟶ Y
r_ne_s : ¬r = s
⊢ False

Next tactic:
have z : (2 : Cardinal) ≤ #(X ⟶ Y) := by
        rw [Cardinal.two_le_iff]
        exact ⟨_, _, r_ne_s⟩
/-- A small category with products is a thin category.

in Lean, a preorder category is one where the morphisms are in Prop, which is weaker than the usual
notion of a preorder/thin category which says that each homset is subsingleton; we show the latter
rather than providing a `Preorder C` instance.
-/
instance (priority := 100) : Quiver.IsThin C := fun X Y =>
  ⟨fun r s => by
    classical
      by_contra r_ne_s
      have z : (2 : Cardinal) ≤ #(X ⟶ Y) := by
        

Proof state:
C : Type u
inst✝¹ : SmallCategory C
inst✝ : HasProducts C
X Y : C
r s : X ⟶ Y
r_ne_s : ¬r = s
⊢ 2 ≤ #(X ⟶ Y)

Next tactic:
rw [Cardinal.two_le_iff]
/-- A small category with products is a thin category.

in Lean, a preorder category is one where the morphisms are in Prop, which is weaker than the usual
notion of a preorder/thin category which says that each homset is subsingleton; we show the latter
rather than providing a `Preorder C` instance.
-/
instance (priority := 100) : Quiver.IsThin C := fun X Y =>
  ⟨fun r s => by
    classical
      by_contra r_ne_s
      have z : (2 : Cardinal) ≤ #(X ⟶ Y) := by
        rw [Cardinal.two_le_iff]
        

Proof state:
C : Type u
inst✝¹ : SmallCategory C
inst✝ : HasProducts C
X Y : C
r s : X ⟶ Y
r_ne_s : ¬r = s
⊢ ∃ x y, x ≠ y

Next tactic:
exact ⟨_, _, r_ne_s⟩
/-- A small category with products is a thin category.

in Lean, a preorder category is one where the morphisms are in Prop, which is weaker than the usual
notion of a preorder/thin category which says that each homset is subsingleton; we show the latter
rather than providing a `Preorder C` instance.
-/
instance (priority := 100) : Quiver.IsThin C := fun X Y =>
  ⟨fun r s => by
    classical
      by_contra r_ne_s
      have z : (2 : Cardinal) ≤ #(X ⟶ Y) := by
        rw [Cardinal.two_le_iff]
        exact ⟨_, _, r_ne_s⟩
      

Proof state:
C : Type u
inst✝¹ : SmallCategory C
inst✝ : HasProducts C
X Y : C
r s : X ⟶ Y
r_ne_s : ¬r = s
z : 2 ≤ #(X ⟶ Y)
⊢ False

Next tactic:
let md := ΣZ W : C, Z ⟶ W
/-- A small category with products is a thin category.

in Lean, a preorder category is one where the morphisms are in Prop, which is weaker than the usual
notion of a preorder/thin category which says that each homset is subsingleton; we show the latter
rather than providing a `Preorder C` instance.
-/
instance (priority := 100) : Quiver.IsThin C := fun X Y =>
  ⟨fun r s => by
    classical
      by_contra r_ne_s
      have z : (2 : Cardinal) ≤ #(X ⟶ Y) := by
        rw [Cardinal.two_le_iff]
        exact ⟨_, _, r_ne_s⟩
      let md := ΣZ W : C, Z ⟶ W
      

Proof state:
C : Type u
inst✝¹ : SmallCategory C
inst✝ : HasProducts C
X Y : C
r s : X ⟶ Y
r_ne_s : ¬r = s
z : 2 ≤ #(X ⟶ Y)
md : Type u := (Z : C) × (W : C) × (Z ⟶ W)
⊢ False

Next tactic:
let α := #md