l3lab/ntp-mathlib huggingface dataset:
lemma hfunext {α α' : Sort u} {β : α → Sort v} {β' : α' → Sort v} {f : ∀a, β a} {f' : ∀a, β' a}
    (hα : α = α') (h : ∀a a', HEq a a' → HEq (f a) (f' a')) : HEq f f' := by
  subst hα
  have : ∀a, HEq (f a) (f' a) := λ a => h a a (HEq.refl a)
  have : β = β' := by funext a
                      exact type_eq_of_heq (this a)
  subst this
  apply heq_of_eq
  funext a
  

Proof state:
case h.h
α✝ : Sort ?u.774
β✝ : Sort ?u.777
γ : Sort ?u.780
f✝ : α✝ → β✝
α : Sort u
β : α → Sort v
f f' : (a : α) → β a
h : ∀ (a a' : α), HEq a a' → HEq (f a) (f' a')
this : ∀ (a : α), HEq (f a) (f' a)
a : α
⊢ f a = f' a

Next tactic:
exact eq_of_heq (this a)
theorem Injective.beq_eq [BEq α] [LawfulBEq α] [BEq β] [LawfulBEq β]
    (I : Injective f) {a b : α} : (f a == f b) = (a == b) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Sort ?u.1351
f : α → β
inst✝³ : BEq α
inst✝² : LawfulBEq α
inst✝¹ : BEq β
inst✝ : LawfulBEq β
I : Injective f
a b : α
⊢ (f a == f b) = (a == b)

Next tactic:
by_cases h : a == b
theorem Injective.beq_eq [BEq α] [LawfulBEq α] [BEq β] [LawfulBEq β]
    (I : Injective f) {a b : α} : (f a == f b) = (a == b) := by
  by_cases h : a == b <;> 

Proof state:
case pos
α : Type u_1
β : Type u_2
γ : Sort ?u.1351
f : α → β
inst✝³ : BEq α
inst✝² : LawfulBEq α
inst✝¹ : BEq β
inst✝ : LawfulBEq β
I : Injective f
a b : α
h : (a == b) = true
⊢ (f a == f b) = (a == b)

Next tactic:
simp [h]
theorem Injective.beq_eq [BEq α] [LawfulBEq α] [BEq β] [LawfulBEq β]
    (I : Injective f) {a b : α} : (f a == f b) = (a == b) := by
  by_cases h : a == b <;> 

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Sort ?u.1351
f : α → β
inst✝³ : BEq α
inst✝² : LawfulBEq α
inst✝¹ : BEq β
inst✝ : LawfulBEq β
I : Injective f
a b : α
h : ¬(a == b) = true
⊢ (f a == f b) = (a == b)

Next tactic:
simp [h]
theorem Injective.beq_eq [BEq α] [LawfulBEq α] [BEq β] [LawfulBEq β]
    (I : Injective f) {a b : α} : (f a == f b) = (a == b) := by
  by_cases h : a == b <;> simp [h] <;> 

Proof state:
case pos
α : Type u_1
β : Type u_2
γ : Sort ?u.1351
f : α → β
inst✝³ : BEq α
inst✝² : LawfulBEq α
inst✝¹ : BEq β
inst✝ : LawfulBEq β
I : Injective f
a b : α
h : (a == b) = true
⊢ f a = f b

Next tactic:
simpa [I.eq_iff] using h
theorem Injective.beq_eq [BEq α] [LawfulBEq α] [BEq β] [LawfulBEq β]
    (I : Injective f) {a b : α} : (f a == f b) = (a == b) := by
  by_cases h : a == b <;> simp [h] <;> 

Proof state:
case neg
α : Type u_1
β : Type u_2
γ : Sort ?u.1351
f : α → β
inst✝³ : BEq α
inst✝² : LawfulBEq α
inst✝¹ : BEq β
inst✝ : LawfulBEq β
I : Injective f
a b : α
h : ¬(a == b) = true
⊢ ¬f a = f b

Next tactic:
simpa [I.eq_iff] using h
theorem Injective.of_comp_right {g : γ → α} (I : Injective (f ∘ g)) (hg : Surjective g) :
    Injective f := fun x y h ↦ by
  

Proof state:
α : Sort u_3
β : Sort u_2
γ : Sort u_1
f : α → β
g : γ → α
I : Injective (f ∘ g)
hg : Surjective g
x y : α
h : f x = f y
⊢ x = y

Next tactic:
obtain ⟨x, rfl⟩ := hg x
theorem Injective.of_comp_right {g : γ → α} (I : Injective (f ∘ g)) (hg : Surjective g) :
    Injective f := fun x y h ↦ by
  obtain ⟨x, rfl⟩ := hg x
  

Proof state:
case intro
α : Sort u_3
β : Sort u_2
γ : Sort u_1
f : α → β
g : γ → α
I : Injective (f ∘ g)
hg : Surjective g
y : α
x : γ
h : f (g x) = f y
⊢ g x = y

Next tactic:
obtain ⟨y, rfl⟩ := hg y
theorem Injective.of_comp_right {g : γ → α} (I : Injective (f ∘ g)) (hg : Surjective g) :
    Injective f := fun x y h ↦ by
  obtain ⟨x, rfl⟩ := hg x
  obtain ⟨y, rfl⟩ := hg y
  

Proof state:
case intro.intro
α : Sort u_3
β : Sort u_2
γ : Sort u_1
f : α → β
g : γ → α
I : Injective (f ∘ g)
hg : Surjective g
x y : γ
h : f (g x) = f (g y)
⊢ g x = g y

Next tactic:
exact congr_arg g (I h)
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by 

Proof state:
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
⊢ Injective fun x => if h : p x then f { val := x, property := h } else f' { val := x, property := h }

Next tactic:
intros x₁ x₂ h
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by intros x₁ x₂ h
   

Proof state:
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
x₁ x₂ : α
h :
  (fun x => if h : p x then f { val := x, property := h } else f' { val := x, property := h }) x₁ =
    (fun x => if h : p x then f { val := x, property := h } else f' { val := x, property := h }) x₂
⊢ x₁ = x₂

Next tactic:
dsimp only at h
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by intros x₁ x₂ h
   dsimp only at h
   

Proof state:
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
x₁ x₂ : α
h :
  (if h : p x₁ then f { val := x₁, property := h } else f' { val := x₁, property := h }) =
    if h : p x₂ then f { val := x₂, property := h } else f' { val := x₂, property := h }
⊢ x₁ = x₂

Next tactic:
by_cases h₁ : p x₁
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by intros x₁ x₂ h
   dsimp only at h
   by_cases h₁ : p x₁ <;> 

Proof state:
case pos
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
x₁ x₂ : α
h :
  (if h : p x₁ then f { val := x₁, property := h } else f' { val := x₁, property := h }) =
    if h : p x₂ then f { val := x₂, property := h } else f' { val := x₂, property := h }
h₁ : p x₁
⊢ x₁ = x₂

Next tactic:
by_cases h₂ : p x₂
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by intros x₁ x₂ h
   dsimp only at h
   by_cases h₁ : p x₁ <;> 

Proof state:
case neg
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
x₁ x₂ : α
h :
  (if h : p x₁ then f { val := x₁, property := h } else f' { val := x₁, property := h }) =
    if h : p x₂ then f { val := x₂, property := h } else f' { val := x₂, property := h }
h₁ : ¬p x₁
⊢ x₁ = x₂

Next tactic:
by_cases h₂ : p x₂
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by intros x₁ x₂ h
   dsimp only at h
   by_cases h₁ : p x₁ <;> by_cases h₂ : p x₂
   · 

Proof state:
case pos
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
x₁ x₂ : α
h :
  (if h : p x₁ then f { val := x₁, property := h } else f' { val := x₁, property := h }) =
    if h : p x₂ then f { val := x₂, property := h } else f' { val := x₂, property := h }
h₁ : p x₁
h₂ : p x₂
⊢ x₁ = x₂

Next tactic:
rw [dif_pos h₁, dif_pos h₂] at h
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by intros x₁ x₂ h
   dsimp only at h
   by_cases h₁ : p x₁ <;> by_cases h₂ : p x₂
   · rw [dif_pos h₁, dif_pos h₂] at h; 

Proof state:
case pos
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
x₁ x₂ : α
h₁ : p x₁
h₂ : p x₂
h : f { val := x₁, property := h₁ } = f { val := x₂, property := h₂ }
⊢ x₁ = x₂

Next tactic:
injection (hf h)
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by intros x₁ x₂ h
   dsimp only at h
   by_cases h₁ : p x₁ <;> by_cases h₂ : p x₂
   · rw [dif_pos h₁, dif_pos h₂] at h; injection (hf h)
   · 

Proof state:
case neg
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
x₁ x₂ : α
h :
  (if h : p x₁ then f { val := x₁, property := h } else f' { val := x₁, property := h }) =
    if h : p x₂ then f { val := x₂, property := h } else f' { val := x₂, property := h }
h₁ : p x₁
h₂ : ¬p x₂
⊢ x₁ = x₂

Next tactic:
rw [dif_pos h₁, dif_neg h₂] at h
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by intros x₁ x₂ h
   dsimp only at h
   by_cases h₁ : p x₁ <;> by_cases h₂ : p x₂
   · rw [dif_pos h₁, dif_pos h₂] at h; injection (hf h)
   · rw [dif_pos h₁, dif_neg h₂] at h; 

Proof state:
case neg
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
x₁ x₂ : α
h₁ : p x₁
h₂ : ¬p x₂
h : f { val := x₁, property := h₁ } = f' { val := x₂, property := h₂ }
⊢ x₁ = x₂

Next tactic:
exact (im_disj h).elim
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by intros x₁ x₂ h
   dsimp only at h
   by_cases h₁ : p x₁ <;> by_cases h₂ : p x₂
   · rw [dif_pos h₁, dif_pos h₂] at h; injection (hf h)
   · rw [dif_pos h₁, dif_neg h₂] at h; exact (im_disj h).elim
   · 

Proof state:
case pos
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
x₁ x₂ : α
h :
  (if h : p x₁ then f { val := x₁, property := h } else f' { val := x₁, property := h }) =
    if h : p x₂ then f { val := x₂, property := h } else f' { val := x₂, property := h }
h₁ : ¬p x₁
h₂ : p x₂
⊢ x₁ = x₂

Next tactic:
rw [dif_neg h₁, dif_pos h₂] at h
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by intros x₁ x₂ h
   dsimp only at h
   by_cases h₁ : p x₁ <;> by_cases h₂ : p x₂
   · rw [dif_pos h₁, dif_pos h₂] at h; injection (hf h)
   · rw [dif_pos h₁, dif_neg h₂] at h; exact (im_disj h).elim
   · rw [dif_neg h₁, dif_pos h₂] at h; 

Proof state:
case pos
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
x₁ x₂ : α
h₁ : ¬p x₁
h₂ : p x₂
h : f' { val := x₁, property := h₁ } = f { val := x₂, property := h₂ }
⊢ x₁ = x₂

Next tactic:
exact (im_disj h.symm).elim
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by intros x₁ x₂ h
   dsimp only at h
   by_cases h₁ : p x₁ <;> by_cases h₂ : p x₂
   · rw [dif_pos h₁, dif_pos h₂] at h; injection (hf h)
   · rw [dif_pos h₁, dif_neg h₂] at h; exact (im_disj h).elim
   · rw [dif_neg h₁, dif_pos h₂] at h; exact (im_disj h.symm).elim
   · 

Proof state:
case neg
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
x₁ x₂ : α
h :
  (if h : p x₁ then f { val := x₁, property := h } else f' { val := x₁, property := h }) =
    if h : p x₂ then f { val := x₂, property := h } else f' { val := x₂, property := h }
h₁ : ¬p x₁
h₂ : ¬p x₂
⊢ x₁ = x₂

Next tactic:
rw [dif_neg h₁, dif_neg h₂] at h
lemma Injective.dite (p : α → Prop) [DecidablePred p]
    {f : {a : α // p a} → β} {f' : {a : α // ¬ p a} → β}
    (hf : Injective f) (hf' : Injective f')
    (im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬ p x'}, f ⟨x, hx⟩ ≠ f' ⟨x', hx'⟩) :
  Function.Injective (λ x => if h : p x then f ⟨x, h⟩ else f' ⟨x, h⟩) :=
by intros x₁ x₂ h
   dsimp only at h
   by_cases h₁ : p x₁ <;> by_cases h₂ : p x₂
   · rw [dif_pos h₁, dif_pos h₂] at h; injection (hf h)
   · rw [dif_pos h₁, dif_neg h₂] at h; exact (im_disj h).elim
   · rw [dif_neg h₁, dif_pos h₂] at h; exact (im_disj h.symm).elim
   · rw [dif_neg h₁, dif_neg h₂] at h; 

Proof state:
case neg
α : Sort u_1
β : Sort u_2
γ : Sort ?u.3760
f✝ : α → β
p : α → Prop
inst✝ : DecidablePred p
f : { a // p a } → β
f' : { a // ¬p a } → β
hf : Injective f
hf' : Injective f'
im_disj : ∀ {x x' : α} {hx : p x} {hx' : ¬p x'}, f { val := x, property := hx } ≠ f' { val := x', property := hx' }
x₁ x₂ : α
h₁ : ¬p x₁
h₂ : ¬p x₂
h : f' { val := x₁, property := h₁ } = f' { val := x₂, property := h₂ }
⊢ x₁ = x₂

Next tactic:
injection (hf' h)
theorem surjective_of_right_cancellable_Prop (h : ∀ g₁ g₂ : β → Prop, g₁ ∘ f = g₂ ∘ f → g₁ = g₂) :
    Surjective f := by
  

Proof state:
α : Sort u_1
β : Sort u_2
γ : Sort ?u.6972
f : α → β
h : ∀ (g₁ g₂ : β → Prop), g₁ ∘ f = g₂ ∘ f → g₁ = g₂
⊢ Surjective f

Next tactic:
specialize h (fun y ↦ ∃ x, f x = y) (fun _ ↦ True) (funext fun x ↦ eq_true ⟨_, rfl⟩)
theorem surjective_of_right_cancellable_Prop (h : ∀ g₁ g₂ : β → Prop, g₁ ∘ f = g₂ ∘ f → g₁ = g₂) :
    Surjective f := by
  specialize h (fun y ↦ ∃ x, f x = y) (fun _ ↦ True) (funext fun x ↦ eq_true ⟨_, rfl⟩)
  

Proof state:
α : Sort u_1
β : Sort u_2
γ : Sort ?u.6972
f : α → β
h : (fun y => ∃ x, f x = y) = fun x => True
⊢ Surjective f

Next tactic:
intro y
theorem surjective_of_right_cancellable_Prop (h : ∀ g₁ g₂ : β → Prop, g₁ ∘ f = g₂ ∘ f → g₁ = g₂) :
    Surjective f := by
  specialize h (fun y ↦ ∃ x, f x = y) (fun _ ↦ True) (funext fun x ↦ eq_true ⟨_, rfl⟩)
  intro y; 

Proof state:
α : Sort u_1
β : Sort u_2
γ : Sort ?u.6972
f : α → β
h : (fun y => ∃ x, f x = y) = fun x => True
y : β
⊢ ∃ a, f a = y

Next tactic:
rw [congr_fun h y]
theorem surjective_of_right_cancellable_Prop (h : ∀ g₁ g₂ : β → Prop, g₁ ∘ f = g₂ ∘ f → g₁ = g₂) :
    Surjective f := by
  specialize h (fun y ↦ ∃ x, f x = y) (fun _ ↦ True) (funext fun x ↦ eq_true ⟨_, rfl⟩)
  intro y; rw [congr_fun h y]; 

Proof state:
α : Sort u_1
β : Sort u_2
γ : Sort ?u.6972
f : α → β
h : (fun y => ∃ x, f x = y) = fun x => True
y : β
⊢ True

Next tactic:
trivial
theorem Bijective.existsUnique_iff {f : α → β} (hf : Bijective f) {p : β → Prop} :
    (∃! y, p y) ↔ ∃! x, p (f x) :=
  ⟨fun ⟨y, hpy, hy⟩ ↦
    let ⟨x, hx⟩ := hf.surjective y
    ⟨x, by 

Proof state:
α : Sort u_1
β : Sort u_2
γ : Sort ?u.7498
f✝ f : α → β
hf : Bijective f
p : β → Prop
x✝ : ∃! y, p y
y : β
hpy : (fun y => p y) y
hy : ∀ (y_1 : β), (fun y => p y) y_1 → y_1 = y
x : α
hx : f x = y
⊢ (fun x => p (f x)) x

Next tactic:
simpa [hx]
theorem Bijective.existsUnique_iff {f : α → β} (hf : Bijective f) {p : β → Prop} :
    (∃! y, p y) ↔ ∃! x, p (f x) :=
  ⟨fun ⟨y, hpy, hy⟩ ↦
    let ⟨x, hx⟩ := hf.surjective y
    ⟨x, by simpa [hx], fun z (hz : p (f z)) ↦ hf.injective <| hx.symm ▸ hy _ hz⟩,
    fun ⟨x, hpx, hx⟩ ↦
    ⟨f x, hpx, fun y hy ↦
      let ⟨z, hz⟩ := hf.surjective y
      hz ▸ congr_arg f (hx _ (by 

Proof state:
α : Sort u_1
β : Sort u_2
γ : Sort ?u.7498
f✝ f : α → β
hf : Bijective f
p : β → Prop
x✝ : ∃! x, p (f x)
x : α
hpx : (fun x => p (f x)) x
hx : ∀ (y : α), (fun x => p (f x)) y → y = x
y : β
hy : (fun y => p y) y
z : α
hz : f z = y
⊢ (fun x => p (f x)) z

Next tactic:
simpa [hz]
/-- There is no surjection from `α : Type u` into `Type (max u v)`. This theorem
  demonstrates why `Type : Type` would be inconsistent in Lean. -/
theorem not_surjective_Type {α : Type u} (f : α → Type max u v) : ¬Surjective f := by
  

Proof state:
α✝ : Sort ?u.9034
β : Sort ?u.9037
γ : Sort ?u.9040
f✝ : α✝ → β
α : Type u
f : α → Type (max u v)
⊢ ¬Surjective f

Next tactic:
intro hf
/-- There is no surjection from `α : Type u` into `Type (max u v)`. This theorem
  demonstrates why `Type : Type` would be inconsistent in Lean. -/
theorem not_surjective_Type {α : Type u} (f : α → Type max u v) : ¬Surjective f := by
  intro hf
  

Proof state:
α✝ : Sort ?u.9034
β : Sort ?u.9037
γ : Sort ?u.9040
f✝ : α✝ → β
α : Type u
f : α → Type (max u v)
hf : Surjective f
⊢ False

Next tactic:
let T : Type max u v := Sigma f
/-- There is no surjection from `α : Type u` into `Type (max u v)`. This theorem
  demonstrates why `Type : Type` would be inconsistent in Lean. -/
theorem not_surjective_Type {α : Type u} (f : α → Type max u v) : ¬Surjective f := by
  intro hf
  let T : Type max u v := Sigma f
  

Proof state:
α✝ : Sort ?u.9034
β : Sort ?u.9037
γ : Sort ?u.9040
f✝ : α✝ → β
α : Type u
f : α → Type (max u v)
hf : Surjective f
T : Type (max u v) := Sigma f
⊢ False

Next tactic:
cases hf (Set T) with | intro U hU =>
  let g : Set T → T := fun s ↦ ⟨U, cast hU.symm s⟩
  have hg : Injective g := by
    intro s t h
    suffices cast hU (g s).2 = cast hU (g t).2 by
      simp only [cast_cast, cast_eq] at this
      assumption
    · congr
  exact cantor_injective g hg
/-- There is no surjection from `α : Type u` into `Type (max u v)`. This theorem
  demonstrates why `Type : Type` would be inconsistent in Lean. -/
theorem not_surjective_Type {α : Type u} (f : α → Type max u v) : ¬Surjective f := by
  intro hf
  let T : Type max u v := Sigma f
  

Proof state:
α✝ : Sort ?u.9034
β : Sort ?u.9037
γ : Sort ?u.9040
f✝ : α✝ → β
α : Type u
f : α → Type (max u v)
hf : Surjective f
T : Type (max u v) := Sigma f
x✝ : ∃ a, f a = Set T
⊢ False

Next tactic:
cases hf (Set T) with | intro U hU =>
  let g : Set T → T := fun s ↦ ⟨U, cast hU.symm s⟩
  have hg : Injective g := by
    intro s t h
    suffices cast hU (g s).2 = cast hU (g t).2 by
      simp only [cast_cast, cast_eq] at this
      assumption
    · congr
  exact cantor_injective g hg
/-- There is no surjection from `α : Type u` into `Type (max u v)`. This theorem
  demonstrates why `Type : Type` would be inconsistent in Lean. -/
theorem not_surjective_Type {α : Type u} (f : α → Type max u v) : ¬Surjective f := by
  intro hf
  let T : Type max u v := Sigma f
  cases hf (Set T) with 

Proof state:
case intro
α✝ : Sort ?u.9034
β : Sort ?u.9037
γ : Sort ?u.9040
f✝ : α✝ → β
α : Type u
f : α → Type (max u v)
hf : Surjective f
T : Type (max u v) := Sigma f
U : α
hU : f U = Set T
⊢ False

Next tactic:
| intro U hU =>
  let g : Set T → T := fun s ↦ ⟨U, cast hU.symm s⟩
  have hg : Injective g := by
    intro s t h
    suffices cast hU (g s).2 = cast hU (g t).2 by
      simp only [cast_cast, cast_eq] at this
      assumption
    · congr
  exact cantor_injective g hg
/-- There is no surjection from `α : Type u` into `Type (max u v)`. This theorem
  demonstrates why `Type : Type` would be inconsistent in Lean. -/
theorem not_surjective_Type {α : Type u} (f : α → Type max u v) : ¬Surjective f := by
  intro hf
  let T : Type max u v := Sigma f
  cases hf (Set T) with | intro U hU =>
  

Proof state:
case intro
α✝ : Sort ?u.9034
β : Sort ?u.9037
γ : Sort ?u.9040
f✝ : α✝ → β
α : Type u
f : α → Type (max u v)
hf : Surjective f
T : Type (max u v) := Sigma f
U : α
hU : f U = Set T
⊢ False

Next tactic:
let g : Set T → T := fun s ↦ ⟨U, cast hU.symm s⟩
/-- There is no surjection from `α : Type u` into `Type (max u v)`. This theorem
  demonstrates why `Type : Type` would be inconsistent in Lean. -/
theorem not_surjective_Type {α : Type u} (f : α → Type max u v) : ¬Surjective f := by
  intro hf
  let T : Type max u v := Sigma f
  cases hf (Set T) with | intro U hU =>
  let g : Set T → T := fun s ↦ ⟨U, cast hU.symm s⟩
  

Proof state:
case intro
α✝ : Sort ?u.9034
β : Sort ?u.9037
γ : Sort ?u.9040
f✝ : α✝ → β
α : Type u
f : α → Type (max u v)
hf : Surjective f
T : Type (max u v) := Sigma f
U : α
hU : f U = Set T
g : Set T → T := fun s => { fst := U, snd := cast (_ : Set T = f U) s }
⊢ False

Next tactic:
have hg : Injective g := by
    intro s t h
    suffices cast hU (g s).2 = cast hU (g t).2 by
      simp only [cast_cast, cast_eq] at this
      assumption
    · congr
/-- There is no surjection from `α : Type u` into `Type (max u v)`. This theorem
  demonstrates why `Type : Type` would be inconsistent in Lean. -/
theorem not_surjective_Type {α : Type u} (f : α → Type max u v) : ¬Surjective f := by
  intro hf
  let T : Type max u v := Sigma f
  cases hf (Set T) with | intro U hU =>
  let g : Set T → T := fun s ↦ ⟨U, cast hU.symm s⟩
  have hg : Injective g := by
    

Proof state:
α✝ : Sort ?u.9034
β : Sort ?u.9037
γ : Sort ?u.9040
f✝ : α✝ → β
α : Type u
f : α → Type (max u v)
hf : Surjective f
T : Type (max u v) := Sigma f
U : α
hU : f U = Set T
g : Set T → T := fun s => { fst := U, snd := cast (_ : Set T = f U) s }
⊢ Injective g

Next tactic:
intro s t h