l3lab/ntp-mathlib huggingface dataset:
theorem chain_iff_pairwise [IsTrans α r] : Chain r s ↔ ∀ a ∈ s, ∀ b ∈ s, r a b :=
  ⟨by
    induction' s using Cycle.induction_on with a l _
    · exact fun _ b hb => (not_mem_nil _ hb).elim
    

Proof state:
case HI
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝ : IsTrans α r
a : α
l : List α
a✝ : Chain r ↑l → ∀ a ∈ ↑l, ∀ b ∈ ↑l, r a b
⊢ Chain r ↑(a :: l) → ∀ a_2 ∈ ↑(a :: l), ∀ b ∈ ↑(a :: l), r a_2 b

Next tactic:
intro hs b hb c hc
theorem chain_iff_pairwise [IsTrans α r] : Chain r s ↔ ∀ a ∈ s, ∀ b ∈ s, r a b :=
  ⟨by
    induction' s using Cycle.induction_on with a l _
    · exact fun _ b hb => (not_mem_nil _ hb).elim
    intro hs b hb c hc
    

Proof state:
case HI
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝ : IsTrans α r
a : α
l : List α
a✝ : Chain r ↑l → ∀ a ∈ ↑l, ∀ b ∈ ↑l, r a b
hs : Chain r ↑(a :: l)
b : α
hb : b ∈ ↑(a :: l)
c : α
hc : c ∈ ↑(a :: l)
⊢ r b c

Next tactic:
rw [Cycle.chain_coe_cons, List.chain_iff_pairwise] at hs
theorem chain_iff_pairwise [IsTrans α r] : Chain r s ↔ ∀ a ∈ s, ∀ b ∈ s, r a b :=
  ⟨by
    induction' s using Cycle.induction_on with a l _
    · exact fun _ b hb => (not_mem_nil _ hb).elim
    intro hs b hb c hc
    rw [Cycle.chain_coe_cons, List.chain_iff_pairwise] at hs
    

Proof state:
case HI
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝ : IsTrans α r
a : α
l : List α
a✝ : Chain r ↑l → ∀ a ∈ ↑l, ∀ b ∈ ↑l, r a b
hs : List.Pairwise r (a :: (l ++ [a]))
b : α
hb : b ∈ ↑(a :: l)
c : α
hc : c ∈ ↑(a :: l)
⊢ r b c

Next tactic:
simp only [pairwise_append, pairwise_cons, mem_append, mem_singleton, List.not_mem_nil,
      IsEmpty.forall_iff, imp_true_iff, Pairwise.nil, forall_eq, true_and_iff] at hs
theorem chain_iff_pairwise [IsTrans α r] : Chain r s ↔ ∀ a ∈ s, ∀ b ∈ s, r a b :=
  ⟨by
    induction' s using Cycle.induction_on with a l _
    · exact fun _ b hb => (not_mem_nil _ hb).elim
    intro hs b hb c hc
    rw [Cycle.chain_coe_cons, List.chain_iff_pairwise] at hs
    simp only [pairwise_append, pairwise_cons, mem_append, mem_singleton, List.not_mem_nil,
      IsEmpty.forall_iff, imp_true_iff, Pairwise.nil, forall_eq, true_and_iff] at hs
    

Proof state:
case HI
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝ : IsTrans α r
a : α
l : List α
a✝ : Chain r ↑l → ∀ a ∈ ↑l, ∀ b ∈ ↑l, r a b
b : α
hb : b ∈ ↑(a :: l)
c : α
hc : c ∈ ↑(a :: l)
hs : (∀ (a' : α), a' ∈ l ∨ a' = a → r a a') ∧ List.Pairwise r l ∧ ∀ a_1 ∈ l, r a_1 a
⊢ r b c

Next tactic:
simp only [mem_coe_iff, mem_cons] at hb hc
theorem chain_iff_pairwise [IsTrans α r] : Chain r s ↔ ∀ a ∈ s, ∀ b ∈ s, r a b :=
  ⟨by
    induction' s using Cycle.induction_on with a l _
    · exact fun _ b hb => (not_mem_nil _ hb).elim
    intro hs b hb c hc
    rw [Cycle.chain_coe_cons, List.chain_iff_pairwise] at hs
    simp only [pairwise_append, pairwise_cons, mem_append, mem_singleton, List.not_mem_nil,
      IsEmpty.forall_iff, imp_true_iff, Pairwise.nil, forall_eq, true_and_iff] at hs
    simp only [mem_coe_iff, mem_cons] at hb hc
    

Proof state:
case HI
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝ : IsTrans α r
a : α
l : List α
a✝ : Chain r ↑l → ∀ a ∈ ↑l, ∀ b ∈ ↑l, r a b
b c : α
hs : (∀ (a' : α), a' ∈ l ∨ a' = a → r a a') ∧ List.Pairwise r l ∧ ∀ a_1 ∈ l, r a_1 a
hb : b = a ∨ b ∈ l
hc : c = a ∨ c ∈ l
⊢ r b c

Next tactic:
rcases hb with (rfl | hb)
theorem chain_iff_pairwise [IsTrans α r] : Chain r s ↔ ∀ a ∈ s, ∀ b ∈ s, r a b :=
  ⟨by
    induction' s using Cycle.induction_on with a l _
    · exact fun _ b hb => (not_mem_nil _ hb).elim
    intro hs b hb c hc
    rw [Cycle.chain_coe_cons, List.chain_iff_pairwise] at hs
    simp only [pairwise_append, pairwise_cons, mem_append, mem_singleton, List.not_mem_nil,
      IsEmpty.forall_iff, imp_true_iff, Pairwise.nil, forall_eq, true_and_iff] at hs
    simp only [mem_coe_iff, mem_cons] at hb hc
    rcases hb with (rfl | hb) <;> 

Proof state:
case HI.inl
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝ : IsTrans α r
l : List α
a✝ : Chain r ↑l → ∀ a ∈ ↑l, ∀ b ∈ ↑l, r a b
b c : α
hs : (∀ (a' : α), a' ∈ l ∨ a' = b → r b a') ∧ List.Pairwise r l ∧ ∀ a ∈ l, r a b
hc : c = b ∨ c ∈ l
⊢ r b c

Next tactic:
rcases hc with (rfl | hc)
theorem chain_iff_pairwise [IsTrans α r] : Chain r s ↔ ∀ a ∈ s, ∀ b ∈ s, r a b :=
  ⟨by
    induction' s using Cycle.induction_on with a l _
    · exact fun _ b hb => (not_mem_nil _ hb).elim
    intro hs b hb c hc
    rw [Cycle.chain_coe_cons, List.chain_iff_pairwise] at hs
    simp only [pairwise_append, pairwise_cons, mem_append, mem_singleton, List.not_mem_nil,
      IsEmpty.forall_iff, imp_true_iff, Pairwise.nil, forall_eq, true_and_iff] at hs
    simp only [mem_coe_iff, mem_cons] at hb hc
    rcases hb with (rfl | hb) <;> 

Proof state:
case HI.inr
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝ : IsTrans α r
a : α
l : List α
a✝ : Chain r ↑l → ∀ a ∈ ↑l, ∀ b ∈ ↑l, r a b
b c : α
hs : (∀ (a' : α), a' ∈ l ∨ a' = a → r a a') ∧ List.Pairwise r l ∧ ∀ a_1 ∈ l, r a_1 a
hc : c = a ∨ c ∈ l
hb : b ∈ l
⊢ r b c

Next tactic:
rcases hc with (rfl | hc)
theorem chain_iff_pairwise [IsTrans α r] : Chain r s ↔ ∀ a ∈ s, ∀ b ∈ s, r a b :=
  ⟨by
    induction' s using Cycle.induction_on with a l _
    · exact fun _ b hb => (not_mem_nil _ hb).elim
    intro hs b hb c hc
    rw [Cycle.chain_coe_cons, List.chain_iff_pairwise] at hs
    simp only [pairwise_append, pairwise_cons, mem_append, mem_singleton, List.not_mem_nil,
      IsEmpty.forall_iff, imp_true_iff, Pairwise.nil, forall_eq, true_and_iff] at hs
    simp only [mem_coe_iff, mem_cons] at hb hc
    rcases hb with (rfl | hb) <;> rcases hc with (rfl | hc)
    · 

Proof state:
case HI.inl.inl
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝ : IsTrans α r
l : List α
a✝ : Chain r ↑l → ∀ a ∈ ↑l, ∀ b ∈ ↑l, r a b
c : α
hs : (∀ (a' : α), a' ∈ l ∨ a' = c → r c a') ∧ List.Pairwise r l ∧ ∀ a ∈ l, r a c
⊢ r c c

Next tactic:
exact hs.1 c (Or.inr rfl)
theorem chain_iff_pairwise [IsTrans α r] : Chain r s ↔ ∀ a ∈ s, ∀ b ∈ s, r a b :=
  ⟨by
    induction' s using Cycle.induction_on with a l _
    · exact fun _ b hb => (not_mem_nil _ hb).elim
    intro hs b hb c hc
    rw [Cycle.chain_coe_cons, List.chain_iff_pairwise] at hs
    simp only [pairwise_append, pairwise_cons, mem_append, mem_singleton, List.not_mem_nil,
      IsEmpty.forall_iff, imp_true_iff, Pairwise.nil, forall_eq, true_and_iff] at hs
    simp only [mem_coe_iff, mem_cons] at hb hc
    rcases hb with (rfl | hb) <;> rcases hc with (rfl | hc)
    · exact hs.1 c (Or.inr rfl)
    · 

Proof state:
case HI.inl.inr
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝ : IsTrans α r
l : List α
a✝ : Chain r ↑l → ∀ a ∈ ↑l, ∀ b ∈ ↑l, r a b
b c : α
hs : (∀ (a' : α), a' ∈ l ∨ a' = b → r b a') ∧ List.Pairwise r l ∧ ∀ a ∈ l, r a b
hc : c ∈ l
⊢ r b c

Next tactic:
exact hs.1 c (Or.inl hc)
theorem chain_iff_pairwise [IsTrans α r] : Chain r s ↔ ∀ a ∈ s, ∀ b ∈ s, r a b :=
  ⟨by
    induction' s using Cycle.induction_on with a l _
    · exact fun _ b hb => (not_mem_nil _ hb).elim
    intro hs b hb c hc
    rw [Cycle.chain_coe_cons, List.chain_iff_pairwise] at hs
    simp only [pairwise_append, pairwise_cons, mem_append, mem_singleton, List.not_mem_nil,
      IsEmpty.forall_iff, imp_true_iff, Pairwise.nil, forall_eq, true_and_iff] at hs
    simp only [mem_coe_iff, mem_cons] at hb hc
    rcases hb with (rfl | hb) <;> rcases hc with (rfl | hc)
    · exact hs.1 c (Or.inr rfl)
    · exact hs.1 c (Or.inl hc)
    · 

Proof state:
case HI.inr.inl
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝ : IsTrans α r
l : List α
a✝ : Chain r ↑l → ∀ a ∈ ↑l, ∀ b ∈ ↑l, r a b
b c : α
hb : b ∈ l
hs : (∀ (a' : α), a' ∈ l ∨ a' = c → r c a') ∧ List.Pairwise r l ∧ ∀ a ∈ l, r a c
⊢ r b c

Next tactic:
exact hs.2.2 b hb
theorem chain_iff_pairwise [IsTrans α r] : Chain r s ↔ ∀ a ∈ s, ∀ b ∈ s, r a b :=
  ⟨by
    induction' s using Cycle.induction_on with a l _
    · exact fun _ b hb => (not_mem_nil _ hb).elim
    intro hs b hb c hc
    rw [Cycle.chain_coe_cons, List.chain_iff_pairwise] at hs
    simp only [pairwise_append, pairwise_cons, mem_append, mem_singleton, List.not_mem_nil,
      IsEmpty.forall_iff, imp_true_iff, Pairwise.nil, forall_eq, true_and_iff] at hs
    simp only [mem_coe_iff, mem_cons] at hb hc
    rcases hb with (rfl | hb) <;> rcases hc with (rfl | hc)
    · exact hs.1 c (Or.inr rfl)
    · exact hs.1 c (Or.inl hc)
    · exact hs.2.2 b hb
    · 

Proof state:
case HI.inr.inr
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝ : IsTrans α r
a : α
l : List α
a✝ : Chain r ↑l → ∀ a ∈ ↑l, ∀ b ∈ ↑l, r a b
b c : α
hs : (∀ (a' : α), a' ∈ l ∨ a' = a → r a a') ∧ List.Pairwise r l ∧ ∀ a_1 ∈ l, r a_1 a
hb : b ∈ l
hc : c ∈ l
⊢ r b c

Next tactic:
exact _root_.trans (hs.2.2 b hb) (hs.1 c (Or.inl hc))
theorem Chain.eq_nil_of_irrefl [IsTrans α r] [IsIrrefl α r] (h : Chain r s) : s = Cycle.nil := by
  

Proof state:
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝¹ : IsTrans α r
inst✝ : IsIrrefl α r
h : Chain r s
⊢ s = Cycle.nil

Next tactic:
induction' s using Cycle.induction_on with a l _ h
theorem Chain.eq_nil_of_irrefl [IsTrans α r] [IsIrrefl α r] (h : Chain r s) : s = Cycle.nil := by
  induction' s using Cycle.induction_on with a l _ h
  · 

Proof state:
case H0
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝¹ : IsTrans α r
inst✝ : IsIrrefl α r
h : Chain r Cycle.nil
⊢ Cycle.nil = Cycle.nil

Next tactic:
rfl
theorem Chain.eq_nil_of_irrefl [IsTrans α r] [IsIrrefl α r] (h : Chain r s) : s = Cycle.nil := by
  induction' s using Cycle.induction_on with a l _ h
  · rfl
  · 

Proof state:
case HI
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝¹ : IsTrans α r
inst✝ : IsIrrefl α r
a : α
l : List α
a✝ : Chain r ↑l → ↑l = Cycle.nil
h : Chain r ↑(a :: l)
⊢ ↑(a :: l) = Cycle.nil

Next tactic:
have ha := mem_cons_self a l
theorem Chain.eq_nil_of_irrefl [IsTrans α r] [IsIrrefl α r] (h : Chain r s) : s = Cycle.nil := by
  induction' s using Cycle.induction_on with a l _ h
  · rfl
  · have ha := mem_cons_self a l
    

Proof state:
case HI
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝¹ : IsTrans α r
inst✝ : IsIrrefl α r
a : α
l : List α
a✝ : Chain r ↑l → ↑l = Cycle.nil
h : Chain r ↑(a :: l)
ha : a ∈ a :: l
⊢ ↑(a :: l) = Cycle.nil

Next tactic:
exact (irrefl_of r a <| chain_iff_pairwise.1 h a ha a ha).elim
theorem forall_eq_of_chain [IsTrans α r] [IsAntisymm α r] (hs : Chain r s) {a b : α} (ha : a ∈ s)
    (hb : b ∈ s) : a = b := by
  

Proof state:
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝¹ : IsTrans α r
inst✝ : IsAntisymm α r
hs : Chain r s
a b : α
ha : a ∈ s
hb : b ∈ s
⊢ a = b

Next tactic:
rw [chain_iff_pairwise] at hs
theorem forall_eq_of_chain [IsTrans α r] [IsAntisymm α r] (hs : Chain r s) {a b : α} (ha : a ∈ s)
    (hb : b ∈ s) : a = b := by
  rw [chain_iff_pairwise] at hs
  

Proof state:
α : Type u_1
r : α → α → Prop
s : Cycle α
inst✝¹ : IsTrans α r
inst✝ : IsAntisymm α r
hs : ∀ a ∈ s, ∀ b ∈ s, r a b
a b : α
ha : a ∈ s
hb : b ∈ s
⊢ a = b

Next tactic:
exact antisymm (hs a ha b hb) (hs b hb a ha)
instance {α : Type*} (β : α → Type*) [Fintype α] [∀ a, Fintype (β a)] : Fintype (Sigma β) :=
  ⟨univ.sigma fun _ => univ, fun ⟨a, b⟩ => by 

Proof state:
α✝ : Type u_1
β✝ : Type u_2
γ : Type u_3
α : Type u_4
β : α → Type u_5
inst✝¹ : Fintype α
inst✝ : (a : α) → Fintype (β a)
x✝ : Sigma β
a : α
b : β a
⊢ { fst := a, snd := b } ∈ Finset.sigma univ fun x => univ

Next tactic:
simp
@[reassoc]
lemma pullback.condition : pullback.fst f g ≫ f = pullback.snd f g ≫ g := by
  

Proof state:
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
⊢ fst f g ≫ f = snd f g ≫ g

Next tactic:
ext ⟨_, h⟩
@[reassoc]
lemma pullback.condition : pullback.fst f g ≫ f = pullback.snd f g ≫ g := by
  ext ⟨_, h⟩
  

Proof state:
case w.mk
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
val✝ : ↑X.toCompHaus.toTop × ↑Y.toCompHaus.toTop
h : val✝ ∈ {xy | f xy.1 = g xy.2}
⊢ (fst f g ≫ f) { val := val✝, property := h } = (snd f g ≫ g) { val := val✝, property := h }

Next tactic:
exact h
/--
Construct a morphism to the explicit pullback given morphisms to the factors
which are compatible with the maps to the base.
This is essentially the universal property of the pullback.
-/
def pullback.lift {Z : Profinite.{u}} (a : Z ⟶ X) (b : Z ⟶ Y) (w : a ≫ f = b ≫ g) :
    Z ⟶ pullback f g where
  toFun := fun z => ⟨⟨a z, b z⟩, by 

Proof state:
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
Z : Profinite
a : Z ⟶ X
b : Z ⟶ Y
w : a ≫ f = b ≫ g
z : ↑Z.toCompHaus.toTop
⊢ (a z, b z) ∈ {xy | f xy.1 = g xy.2}

Next tactic:
apply_fun (· z) at w
/--
Construct a morphism to the explicit pullback given morphisms to the factors
which are compatible with the maps to the base.
This is essentially the universal property of the pullback.
-/
def pullback.lift {Z : Profinite.{u}} (a : Z ⟶ X) (b : Z ⟶ Y) (w : a ≫ f = b ≫ g) :
    Z ⟶ pullback f g where
  toFun := fun z => ⟨⟨a z, b z⟩, by apply_fun (· z) at w; 

Proof state:
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
Z : Profinite
a : Z ⟶ X
b : Z ⟶ Y
z : ↑Z.toCompHaus.toTop
w : (a ≫ f) z = (b ≫ g) z
⊢ (a z, b z) ∈ {xy | f xy.1 = g xy.2}

Next tactic:
exact w
/--
Construct a morphism to the explicit pullback given morphisms to the factors
which are compatible with the maps to the base.
This is essentially the universal property of the pullback.
-/
def pullback.lift {Z : Profinite.{u}} (a : Z ⟶ X) (b : Z ⟶ Y) (w : a ≫ f = b ≫ g) :
    Z ⟶ pullback f g where
  toFun := fun z => ⟨⟨a z, b z⟩, by apply_fun (· z) at w; exact w⟩
  continuous_toFun := by
    

Proof state:
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
Z : Profinite
a : Z ⟶ X
b : Z ⟶ Y
w : a ≫ f = b ≫ g
⊢ Continuous fun z => { val := (a z, b z), property := (_ : (a ≫ f) z = (b ≫ g) z) }

Next tactic:
apply Continuous.subtype_mk
/--
Construct a morphism to the explicit pullback given morphisms to the factors
which are compatible with the maps to the base.
This is essentially the universal property of the pullback.
-/
def pullback.lift {Z : Profinite.{u}} (a : Z ⟶ X) (b : Z ⟶ Y) (w : a ≫ f = b ≫ g) :
    Z ⟶ pullback f g where
  toFun := fun z => ⟨⟨a z, b z⟩, by apply_fun (· z) at w; exact w⟩
  continuous_toFun := by
    apply Continuous.subtype_mk
    

Proof state:
case h
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
Z : Profinite
a : Z ⟶ X
b : Z ⟶ Y
w : a ≫ f = b ≫ g
⊢ Continuous fun x => (a x, b x)

Next tactic:
rw [continuous_prod_mk]
/--
Construct a morphism to the explicit pullback given morphisms to the factors
which are compatible with the maps to the base.
This is essentially the universal property of the pullback.
-/
def pullback.lift {Z : Profinite.{u}} (a : Z ⟶ X) (b : Z ⟶ Y) (w : a ≫ f = b ≫ g) :
    Z ⟶ pullback f g where
  toFun := fun z => ⟨⟨a z, b z⟩, by apply_fun (· z) at w; exact w⟩
  continuous_toFun := by
    apply Continuous.subtype_mk
    rw [continuous_prod_mk]
    

Proof state:
case h
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
Z : Profinite
a : Z ⟶ X
b : Z ⟶ Y
w : a ≫ f = b ≫ g
⊢ (Continuous fun x => a x) ∧ Continuous fun x => b x

Next tactic:
exact ⟨a.continuous, b.continuous⟩
lemma pullback.hom_ext {Z : Profinite.{u}} (a b : Z ⟶ pullback f g)
    (hfst : a ≫ pullback.fst f g = b ≫ pullback.fst f g)
    (hsnd : a ≫ pullback.snd f g = b ≫ pullback.snd f g) : a = b := by
  

Proof state:
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
Z : Profinite
a b : Z ⟶ pullback f g
hfst : a ≫ fst f g = b ≫ fst f g
hsnd : a ≫ snd f g = b ≫ snd f g
⊢ a = b

Next tactic:
ext z
lemma pullback.hom_ext {Z : Profinite.{u}} (a b : Z ⟶ pullback f g)
    (hfst : a ≫ pullback.fst f g = b ≫ pullback.fst f g)
    (hsnd : a ≫ pullback.snd f g = b ≫ pullback.snd f g) : a = b := by
  ext z
  

Proof state:
case w
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
Z : Profinite
a b : Z ⟶ pullback f g
hfst : a ≫ fst f g = b ≫ fst f g
hsnd : a ≫ snd f g = b ≫ snd f g
z : (forget Profinite).obj Z
⊢ a z = b z

Next tactic:
apply_fun (· z) at hfst hsnd
lemma pullback.hom_ext {Z : Profinite.{u}} (a b : Z ⟶ pullback f g)
    (hfst : a ≫ pullback.fst f g = b ≫ pullback.fst f g)
    (hsnd : a ≫ pullback.snd f g = b ≫ pullback.snd f g) : a = b := by
  ext z
  apply_fun (· z) at hfst hsnd
  

Proof state:
case w
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
Z : Profinite
a b : Z ⟶ pullback f g
z : (forget Profinite).obj Z
hfst : (a ≫ fst f g) z = (b ≫ fst f g) z
hsnd : (a ≫ snd f g) z = (b ≫ snd f g) z
⊢ a z = b z

Next tactic:
apply Subtype.ext
lemma pullback.hom_ext {Z : Profinite.{u}} (a b : Z ⟶ pullback f g)
    (hfst : a ≫ pullback.fst f g = b ≫ pullback.fst f g)
    (hsnd : a ≫ pullback.snd f g = b ≫ pullback.snd f g) : a = b := by
  ext z
  apply_fun (· z) at hfst hsnd
  apply Subtype.ext
  

Proof state:
case w.a
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
Z : Profinite
a b : Z ⟶ pullback f g
z : (forget Profinite).obj Z
hfst : (a ≫ fst f g) z = (b ≫ fst f g) z
hsnd : (a ≫ snd f g) z = (b ≫ snd f g) z
⊢ ↑(a z) = ↑(b z)

Next tactic:
apply Prod.ext
lemma pullback.hom_ext {Z : Profinite.{u}} (a b : Z ⟶ pullback f g)
    (hfst : a ≫ pullback.fst f g = b ≫ pullback.fst f g)
    (hsnd : a ≫ pullback.snd f g = b ≫ pullback.snd f g) : a = b := by
  ext z
  apply_fun (· z) at hfst hsnd
  apply Subtype.ext
  apply Prod.ext
  · 

Proof state:
case w.a.a
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
Z : Profinite
a b : Z ⟶ pullback f g
z : (forget Profinite).obj Z
hfst : (a ≫ fst f g) z = (b ≫ fst f g) z
hsnd : (a ≫ snd f g) z = (b ≫ snd f g) z
⊢ (↑(a z)).1 = (↑(b z)).1

Next tactic:
exact hfst
lemma pullback.hom_ext {Z : Profinite.{u}} (a b : Z ⟶ pullback f g)
    (hfst : a ≫ pullback.fst f g = b ≫ pullback.fst f g)
    (hsnd : a ≫ pullback.snd f g = b ≫ pullback.snd f g) : a = b := by
  ext z
  apply_fun (· z) at hfst hsnd
  apply Subtype.ext
  apply Prod.ext
  · exact hfst
  · 

Proof state:
case w.a.a
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
Z : Profinite
a b : Z ⟶ pullback f g
z : (forget Profinite).obj Z
hfst : (a ≫ fst f g) z = (b ≫ fst f g) z
hsnd : (a ≫ snd f g) z = (b ≫ snd f g) z
⊢ (↑(a z)).2 = (↑(b z)).2

Next tactic:
exact hsnd
theorem pullback_fst_eq :
    Profinite.pullback.fst f g = (pullbackIsoPullback f g).hom ≫ Limits.pullback.fst := by
  

Proof state:
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
⊢ pullback.fst f g = (pullbackIsoPullback f g).hom ≫ Limits.pullback.fst

Next tactic:
dsimp [pullbackIsoPullback]
theorem pullback_fst_eq :
    Profinite.pullback.fst f g = (pullbackIsoPullback f g).hom ≫ Limits.pullback.fst := by
  dsimp [pullbackIsoPullback]
  

Proof state:
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
⊢ pullback.fst f g =
    (IsLimit.conePointUniqueUpToIso (pullback.isLimit f g) (limit.isLimit (cospan f g))).hom ≫ Limits.pullback.fst

Next tactic:
simp only [Limits.limit.conePointUniqueUpToIso_hom_comp, pullback.cone_pt, pullback.cone_π]
theorem pullback_snd_eq :
    Profinite.pullback.snd f g = (pullbackIsoPullback f g).hom ≫ Limits.pullback.snd := by
  

Proof state:
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
⊢ pullback.snd f g = (pullbackIsoPullback f g).hom ≫ Limits.pullback.snd

Next tactic:
dsimp [pullbackIsoPullback]
theorem pullback_snd_eq :
    Profinite.pullback.snd f g = (pullbackIsoPullback f g).hom ≫ Limits.pullback.snd := by
  dsimp [pullbackIsoPullback]
  

Proof state:
X Y B : Profinite
f : X ⟶ B
g : Y ⟶ B
⊢ pullback.snd f g =
    (IsLimit.conePointUniqueUpToIso (pullback.isLimit f g) (limit.isLimit (cospan f g))).hom ≫ Limits.pullback.snd

Next tactic:
simp only [Limits.limit.conePointUniqueUpToIso_hom_comp, pullback.cone_pt, pullback.cone_π]
/--
To construct a morphism from the explicit finite coproduct, it suffices to
specify a morphism from each of its factors.
This is essentially the universal property of the coproduct.
-/
def finiteCoproduct.desc {B : Profinite.{u}} (e : (a : α) → (X a ⟶ B)) :
    finiteCoproduct X ⟶ B where
  toFun := fun ⟨a, x⟩ => e a x
  continuous_toFun := by
    

Proof state:
α : Type
inst✝ : Fintype α
X : α → Profinite
B : Profinite
e : (a : α) → X a ⟶ B
⊢ Continuous fun x =>
    match x with
    | { fst := a, snd := x } => (e a) x

Next tactic:
apply continuous_sigma
/--
To construct a morphism from the explicit finite coproduct, it suffices to
specify a morphism from each of its factors.
This is essentially the universal property of the coproduct.
-/
def finiteCoproduct.desc {B : Profinite.{u}} (e : (a : α) → (X a ⟶ B)) :
    finiteCoproduct X ⟶ B where
  toFun := fun ⟨a, x⟩ => e a x
  continuous_toFun := by
    apply continuous_sigma
    

Proof state:
case hf
α : Type
inst✝ : Fintype α
X : α → Profinite
B : Profinite
e : (a : α) → X a ⟶ B
⊢ ∀ (i : α),
    Continuous fun a =>
      match { fst := i, snd := a } with
      | { fst := a, snd := x } => (e a) x

Next tactic:
intro a
/--
To construct a morphism from the explicit finite coproduct, it suffices to
specify a morphism from each of its factors.
This is essentially the universal property of the coproduct.
-/
def finiteCoproduct.desc {B : Profinite.{u}} (e : (a : α) → (X a ⟶ B)) :
    finiteCoproduct X ⟶ B where
  toFun := fun ⟨a, x⟩ => e a x
  continuous_toFun := by
    apply continuous_sigma
    intro a
    

Proof state:
case hf
α : Type
inst✝ : Fintype α
X : α → Profinite
B : Profinite
e : (a : α) → X a ⟶ B
a : α
⊢ Continuous fun a_1 =>
    match { fst := a, snd := a_1 } with
    | { fst := a, snd := x } => (e a) x

Next tactic:
exact (e a).continuous
lemma finiteCoproduct.hom_ext {B : Profinite.{u}} (f g : finiteCoproduct X ⟶ B)
    (h : ∀ a : α, finiteCoproduct.ι X a ≫ f = finiteCoproduct.ι X a ≫ g) : f = g := by
  

Proof state:
α : Type
inst✝ : Fintype α
X : α → Profinite
B : Profinite
f g : finiteCoproduct X ⟶ B
h : ∀ (a : α), ι X a ≫ f = ι X a ≫ g
⊢ f = g

Next tactic:
ext ⟨a, x⟩
lemma finiteCoproduct.hom_ext {B : Profinite.{u}} (f g : finiteCoproduct X ⟶ B)
    (h : ∀ a : α, finiteCoproduct.ι X a ≫ f = finiteCoproduct.ι X a ≫ g) : f = g := by
  ext ⟨a, x⟩
  

Proof state:
case w.mk
α : Type
inst✝ : Fintype α
X : α → Profinite
B : Profinite
f g : finiteCoproduct X ⟶ B
h : ∀ (a : α), ι X a ≫ f = ι X a ≫ g
a : α
x : ↑(X a).toCompHaus.toTop
⊢ f { fst := a, snd := x } = g { fst := a, snd := x }

Next tactic:
specialize h a
lemma finiteCoproduct.hom_ext {B : Profinite.{u}} (f g : finiteCoproduct X ⟶ B)
    (h : ∀ a : α, finiteCoproduct.ι X a ≫ f = finiteCoproduct.ι X a ≫ g) : f = g := by
  ext ⟨a, x⟩
  specialize h a
  

Proof state:
case w.mk
α : Type
inst✝ : Fintype α
X : α → Profinite
B : Profinite
f g : finiteCoproduct X ⟶ B
a : α
x : ↑(X a).toCompHaus.toTop
h : ι X a ≫ f = ι X a ≫ g
⊢ f { fst := a, snd := x } = g { fst := a, snd := x }

Next tactic:
apply_fun (· x) at h
lemma finiteCoproduct.hom_ext {B : Profinite.{u}} (f g : finiteCoproduct X ⟶ B)
    (h : ∀ a : α, finiteCoproduct.ι X a ≫ f = finiteCoproduct.ι X a ≫ g) : f = g := by
  ext ⟨a, x⟩
  specialize h a
  apply_fun (· x) at h
  

Proof state:
case w.mk
α : Type
inst✝ : Fintype α
X : α → Profinite
B : Profinite
f g : finiteCoproduct X ⟶ B
a : α
x : ↑(X a).toCompHaus.toTop
h : (ι X a ≫ f) x = (ι X a ≫ g) x
⊢ f { fst := a, snd := x } = g { fst := a, snd := x }

Next tactic:
exact h
/-- The explicit finite coproduct cocone is a colimit cocone. -/
@[simps]
def finiteCoproduct.isColimit : Limits.IsColimit (finiteCoproduct.cocone X) where
  desc := fun s => finiteCoproduct.desc _ fun a => s.ι.app ⟨a⟩
  fac := fun s ⟨a⟩ => finiteCoproduct.ι_desc _ _ _
  uniq := fun s m hm => finiteCoproduct.hom_ext _ _ _ fun a => by
    

Proof state:
α : Type
inst✝ : Fintype α
X : α → Profinite
s : Cocone (Discrete.functor X)
m : (cocone X).pt ⟶ s.pt
hm : ∀ (j : Discrete α), (cocone X).ι.app j ≫ m = s.ι.app j
a : α
⊢ ι (fun a => X a) a ≫ m = ι (fun a => X a) a ≫ (fun s => desc (fun a => X a) fun a => s.ι.app { as := a }) s

Next tactic:
specialize hm ⟨a⟩
/-- The explicit finite coproduct cocone is a colimit cocone. -/
@[simps]
def finiteCoproduct.isColimit : Limits.IsColimit (finiteCoproduct.cocone X) where
  desc := fun s => finiteCoproduct.desc _ fun a => s.ι.app ⟨a⟩
  fac := fun s ⟨a⟩ => finiteCoproduct.ι_desc _ _ _
  uniq := fun s m hm => finiteCoproduct.hom_ext _ _ _ fun a => by
    specialize hm ⟨a⟩
    

Proof state:
α : Type
inst✝ : Fintype α
X : α → Profinite
s : Cocone (Discrete.functor X)
m : (cocone X).pt ⟶ s.pt
a : α
hm : (cocone X).ι.app { as := a } ≫ m = s.ι.app { as := a }
⊢ ι (fun a => X a) a ≫ m = ι (fun a => X a) a ≫ (fun s => desc (fun a => X a) fun a => s.ι.app { as := a }) s

Next tactic:
ext t