l3lab/ntp-mathlib huggingface dataset:
theorem setOf_subset_eq_univ_iff (S : L[[α]].Theory) :
    { p : T.CompleteType α | S ⊆ ↑p } = Set.univ ↔
      ∀ φ, φ ∈ S → (L.lhomWithConstants α).onTheory T ⊨ᵇ φ := by
  have h : { p : T.CompleteType α | S ⊆ ↑p } = ⋂₀ ((fun φ => { p | φ ∈ p }) '' S) := by
    ext
    simp [subset_def]
  

Proof state:
L : Language
T : Theory L
α : Type w
S : Theory (L[[α]])
h : {p | S ⊆ ↑p} = ⋂₀ ((fun φ => {p | φ ∈ p}) '' S)
⊢ {p | S ⊆ ↑p} = Set.univ ↔ ∀ φ ∈ S, LHom.onTheory (lhomWithConstants L α) T ⊨ᵇ φ

Next tactic:
simp_rw [h, sInter_eq_univ, ← setOf_mem_eq_univ_iff]
theorem setOf_subset_eq_univ_iff (S : L[[α]].Theory) :
    { p : T.CompleteType α | S ⊆ ↑p } = Set.univ ↔
      ∀ φ, φ ∈ S → (L.lhomWithConstants α).onTheory T ⊨ᵇ φ := by
  have h : { p : T.CompleteType α | S ⊆ ↑p } = ⋂₀ ((fun φ => { p | φ ∈ p }) '' S) := by
    ext
    simp [subset_def]
  simp_rw [h, sInter_eq_univ, ← setOf_mem_eq_univ_iff]
  

Proof state:
L : Language
T : Theory L
α : Type w
S : Theory (L[[α]])
h : {p | S ⊆ ↑p} = ⋂₀ ((fun φ => {p | φ ∈ p}) '' S)
⊢ (∀ s ∈ (fun φ => {p | φ ∈ p}) '' S, s = Set.univ) ↔ ∀ φ ∈ S, {p | φ ∈ p} = Set.univ

Next tactic:
refine' ⟨fun h φ φS => h _ ⟨_, φS, rfl⟩, _⟩
theorem setOf_subset_eq_univ_iff (S : L[[α]].Theory) :
    { p : T.CompleteType α | S ⊆ ↑p } = Set.univ ↔
      ∀ φ, φ ∈ S → (L.lhomWithConstants α).onTheory T ⊨ᵇ φ := by
  have h : { p : T.CompleteType α | S ⊆ ↑p } = ⋂₀ ((fun φ => { p | φ ∈ p }) '' S) := by
    ext
    simp [subset_def]
  simp_rw [h, sInter_eq_univ, ← setOf_mem_eq_univ_iff]
  refine' ⟨fun h φ φS => h _ ⟨_, φS, rfl⟩, _⟩
  

Proof state:
L : Language
T : Theory L
α : Type w
S : Theory (L[[α]])
h : {p | S ⊆ ↑p} = ⋂₀ ((fun φ => {p | φ ∈ p}) '' S)
⊢ (∀ φ ∈ S, {p | φ ∈ p} = Set.univ) → ∀ s ∈ (fun φ => {p | φ ∈ p}) '' S, s = Set.univ

Next tactic:
rintro h _ ⟨φ, h1, rfl⟩
theorem setOf_subset_eq_univ_iff (S : L[[α]].Theory) :
    { p : T.CompleteType α | S ⊆ ↑p } = Set.univ ↔
      ∀ φ, φ ∈ S → (L.lhomWithConstants α).onTheory T ⊨ᵇ φ := by
  have h : { p : T.CompleteType α | S ⊆ ↑p } = ⋂₀ ((fun φ => { p | φ ∈ p }) '' S) := by
    ext
    simp [subset_def]
  simp_rw [h, sInter_eq_univ, ← setOf_mem_eq_univ_iff]
  refine' ⟨fun h φ φS => h _ ⟨_, φS, rfl⟩, _⟩
  rintro h _ ⟨φ, h1, rfl⟩
  

Proof state:
case intro.intro
L : Language
T : Theory L
α : Type w
S : Theory (L[[α]])
h✝ : {p | S ⊆ ↑p} = ⋂₀ ((fun φ => {p | φ ∈ p}) '' S)
h : ∀ φ ∈ S, {p | φ ∈ p} = Set.univ
φ : Sentence (L[[α]])
h1 : φ ∈ S
⊢ (fun φ => {p | φ ∈ p}) φ = Set.univ

Next tactic:
exact h _ h1
theorem nonempty_iff : Nonempty (T.CompleteType α) ↔ T.IsSatisfiable := by
  

Proof state:
L : Language
T : Theory L
α : Type w
⊢ Nonempty (CompleteType T α) ↔ IsSatisfiable T

Next tactic:
rw [← isSatisfiable_onTheory_iff (lhomWithConstants_injective L α)]
theorem nonempty_iff : Nonempty (T.CompleteType α) ↔ T.IsSatisfiable := by
  rw [← isSatisfiable_onTheory_iff (lhomWithConstants_injective L α)]
  

Proof state:
L : Language
T : Theory L
α : Type w
⊢ Nonempty (CompleteType T α) ↔ IsSatisfiable (LHom.onTheory (lhomWithConstants L α) T)

Next tactic:
rw [nonempty_iff_univ_nonempty, nonempty_iff_ne_empty, Ne.def, not_iff_comm,
    ← union_empty ((L.lhomWithConstants α).onTheory T), ← setOf_subset_eq_empty_iff]
theorem nonempty_iff : Nonempty (T.CompleteType α) ↔ T.IsSatisfiable := by
  rw [← isSatisfiable_onTheory_iff (lhomWithConstants_injective L α)]
  rw [nonempty_iff_univ_nonempty, nonempty_iff_ne_empty, Ne.def, not_iff_comm,
    ← union_empty ((L.lhomWithConstants α).onTheory T), ← setOf_subset_eq_empty_iff]
  

Proof state:
L : Language
T : Theory L
α : Type w
⊢ {p | ∅ ⊆ ↑p} = ∅ ↔ Set.univ = ∅

Next tactic:
simp
theorem iInter_setOf_subset {ι : Type*} (S : ι → L[[α]].Theory) :
    ⋂ i : ι, { p : T.CompleteType α | S i ⊆ p } =
      { p : T.CompleteType α | ⋃ i : ι, S i ⊆ p } := by
  

Proof state:
L : Language
T : Theory L
α : Type w
ι : Type u_1
S : ι → Theory (L[[α]])
⊢ ⋂ i, {p | S i ⊆ ↑p} = {p | ⋃ i, S i ⊆ ↑p}

Next tactic:
ext
theorem iInter_setOf_subset {ι : Type*} (S : ι → L[[α]].Theory) :
    ⋂ i : ι, { p : T.CompleteType α | S i ⊆ p } =
      { p : T.CompleteType α | ⋃ i : ι, S i ⊆ p } := by
  ext
  

Proof state:
case h
L : Language
T : Theory L
α : Type w
ι : Type u_1
S : ι → Theory (L[[α]])
x✝ : CompleteType T α
⊢ x✝ ∈ ⋂ i, {p | S i ⊆ ↑p} ↔ x✝ ∈ {p | ⋃ i, S i ⊆ ↑p}

Next tactic:
simp only [mem_iInter, mem_setOf_eq, iUnion_subset_iff]
theorem toList_foldr_inf_mem {p : T.CompleteType α} {t : Finset (L[[α]]).Sentence} :
    t.toList.foldr (· ⊓ ·) ⊤ ∈ p ↔ (t : L[[α]].Theory) ⊆ ↑p := by
  

Proof state:
L : Language
T : Theory L
α : Type w
p : CompleteType T α
t : Finset (Sentence (L[[α]]))
⊢ List.foldr (fun x x_1 => x ⊓ x_1) ⊤ (Finset.toList t) ∈ p ↔ ↑t ⊆ ↑p

Next tactic:
simp_rw [subset_def, ← SetLike.mem_coe, p.isMaximal.mem_iff_models, models_sentence_iff,
    Sentence.Realize, Formula.Realize, BoundedFormula.realize_foldr_inf, Finset.mem_toList]
theorem toList_foldr_inf_mem {p : T.CompleteType α} {t : Finset (L[[α]]).Sentence} :
    t.toList.foldr (· ⊓ ·) ⊤ ∈ p ↔ (t : L[[α]].Theory) ⊆ ↑p := by
  simp_rw [subset_def, ← SetLike.mem_coe, p.isMaximal.mem_iff_models, models_sentence_iff,
    Sentence.Realize, Formula.Realize, BoundedFormula.realize_foldr_inf, Finset.mem_toList]
  

Proof state:
L : Language
T : Theory L
α : Type w
p : CompleteType T α
t : Finset (Sentence (L[[α]]))
⊢ (∀ (M : ModelType ↑p), ∀ φ ∈ t, BoundedFormula.Realize φ default default) ↔
    ∀ x ∈ ↑t, ∀ (M : ModelType ↑p), BoundedFormula.Realize x default default

Next tactic:
exact ⟨fun h φ hφ M => h _ _ hφ, fun h M φ hφ => h _ hφ _⟩
theorem formula_mem_typeOf {φ : L.Formula α} : Formula.equivSentence φ ∈ T.typeOf v ↔ φ.Realize v :=
  by 

Proof state:
L : Language
T : Theory L
α : Type w
M : Type w'
inst✝² : Structure L M
inst✝¹ : Nonempty M
inst✝ : M ⊨ T
v : α → M
φ : Formula L α
⊢ Formula.equivSentence φ ∈ typeOf T v ↔ Formula.Realize φ v

Next tactic:
simp
theorem exists_modelType_is_realized_in (p : T.CompleteType α) :
    ∃ M : Theory.ModelType.{u, v, max u v w} T, p ∈ T.realizedTypes M α := by
  

Proof state:
L : Language
T : Theory L
α : Type w
M : Type w'
inst✝² : Structure L M
inst✝¹ : Nonempty M
inst✝ : M ⊨ T
p : CompleteType T α
⊢ ∃ M, p ∈ realizedTypes T (↑M) α

Next tactic:
obtain ⟨M⟩ := p.isMaximal.1
theorem exists_modelType_is_realized_in (p : T.CompleteType α) :
    ∃ M : Theory.ModelType.{u, v, max u v w} T, p ∈ T.realizedTypes M α := by
  obtain ⟨M⟩ := p.isMaximal.1
  

Proof state:
case intro
L : Language
T : Theory L
α : Type w
M✝ : Type w'
inst✝² : Structure L M✝
inst✝¹ : Nonempty M✝
inst✝ : M✝ ⊨ T
p : CompleteType T α
M : ModelType ↑p
⊢ ∃ M, p ∈ realizedTypes T (↑M) α

Next tactic:
refine' ⟨(M.subtheoryModel p.subset).reduct (L.lhomWithConstants α), fun a => (L.con a : M), _⟩
theorem exists_modelType_is_realized_in (p : T.CompleteType α) :
    ∃ M : Theory.ModelType.{u, v, max u v w} T, p ∈ T.realizedTypes M α := by
  obtain ⟨M⟩ := p.isMaximal.1
  refine' ⟨(M.subtheoryModel p.subset).reduct (L.lhomWithConstants α), fun a => (L.con a : M), _⟩
  

Proof state:
case intro
L : Language
T : Theory L
α : Type w
M✝ : Type w'
inst✝² : Structure L M✝
inst✝¹ : Nonempty M✝
inst✝ : M✝ ⊨ T
p : CompleteType T α
M : ModelType ↑p
⊢ (typeOf T fun a => ↑(Language.con L a)) = p

Next tactic:
refine' SetLike.ext fun φ => _
theorem exists_modelType_is_realized_in (p : T.CompleteType α) :
    ∃ M : Theory.ModelType.{u, v, max u v w} T, p ∈ T.realizedTypes M α := by
  obtain ⟨M⟩ := p.isMaximal.1
  refine' ⟨(M.subtheoryModel p.subset).reduct (L.lhomWithConstants α), fun a => (L.con a : M), _⟩
  refine' SetLike.ext fun φ => _
  

Proof state:
case intro
L : Language
T : Theory L
α : Type w
M✝ : Type w'
inst✝² : Structure L M✝
inst✝¹ : Nonempty M✝
inst✝ : M✝ ⊨ T
p : CompleteType T α
M : ModelType ↑p
φ : Sentence (L[[α]])
⊢ (φ ∈ typeOf T fun a => ↑(Language.con L a)) ↔ φ ∈ p

Next tactic:
simp only [CompleteType.mem_typeOf]
theorem exists_modelType_is_realized_in (p : T.CompleteType α) :
    ∃ M : Theory.ModelType.{u, v, max u v w} T, p ∈ T.realizedTypes M α := by
  obtain ⟨M⟩ := p.isMaximal.1
  refine' ⟨(M.subtheoryModel p.subset).reduct (L.lhomWithConstants α), fun a => (L.con a : M), _⟩
  refine' SetLike.ext fun φ => _
  simp only [CompleteType.mem_typeOf]
  

Proof state:
case intro
L : Language
T : Theory L
α : Type w
M✝ : Type w'
inst✝² : Structure L M✝
inst✝¹ : Nonempty M✝
inst✝ : M✝ ⊨ T
p : CompleteType T α
M : ModelType ↑p
φ : Sentence (L[[α]])
⊢ (Formula.Realize (Formula.equivSentence.symm φ) fun a => ↑(Language.con L a)) ↔ φ ∈ p

Next tactic:
refine'
    (@Formula.realize_equivSentence_symm_con _
      ((M.subtheoryModel p.subset).reduct (L.lhomWithConstants α)) _ _ M.struc _ φ).trans
      (_root_.trans (_root_.trans _ (p.isMaximal.isComplete.realize_sentence_iff φ M))
        (p.isMaximal.mem_iff_models φ).symm)
theorem exists_modelType_is_realized_in (p : T.CompleteType α) :
    ∃ M : Theory.ModelType.{u, v, max u v w} T, p ∈ T.realizedTypes M α := by
  obtain ⟨M⟩ := p.isMaximal.1
  refine' ⟨(M.subtheoryModel p.subset).reduct (L.lhomWithConstants α), fun a => (L.con a : M), _⟩
  refine' SetLike.ext fun φ => _
  simp only [CompleteType.mem_typeOf]
  refine'
    (@Formula.realize_equivSentence_symm_con _
      ((M.subtheoryModel p.subset).reduct (L.lhomWithConstants α)) _ _ M.struc _ φ).trans
      (_root_.trans (_root_.trans _ (p.isMaximal.isComplete.realize_sentence_iff φ M))
        (p.isMaximal.mem_iff_models φ).symm)
  

Proof state:
case intro
L : Language
T : Theory L
α : Type w
M✝ : Type w'
inst✝² : Structure L M✝
inst✝¹ : Nonempty M✝
inst✝ : M✝ ⊨ T
p : CompleteType T α
M : ModelType ↑p
φ : Sentence (L[[α]])
⊢ ↑(ModelType.reduct (lhomWithConstants L α)
          (ModelType.subtheoryModel M (_ : LHom.onTheory (lhomWithConstants L α) T ⊆ ↑p))) ⊨
      φ ↔
    ↑M ⊨ φ

Next tactic:
rfl
instance : CompleteLattice (Presieve X) := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z : C
f : Y ⟶ X
⊢ CompleteLattice (Presieve X)

Next tactic:
dsimp [Presieve]
instance : CompleteLattice (Presieve X) := by
  dsimp [Presieve]
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z : C
f : Y ⟶ X
⊢ CompleteLattice (⦃Y : C⦄ → Set (Y ⟶ X))

Next tactic:
infer_instance
@[simp]
theorem singleton_eq_iff_domain (f g : Y ⟶ X) : singleton f g ↔ f = g := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z : C
f✝ f g : Y ⟶ X
⊢ singleton f g ↔ f = g

Next tactic:
constructor
@[simp]
theorem singleton_eq_iff_domain (f g : Y ⟶ X) : singleton f g ↔ f = g := by
  constructor
  · 

Proof state:
case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z : C
f✝ f g : Y ⟶ X
⊢ singleton f g → f = g

Next tactic:
rintro ⟨a, rfl⟩
@[simp]
theorem singleton_eq_iff_domain (f g : Y ⟶ X) : singleton f g ↔ f = g := by
  constructor
  · rintro ⟨a, rfl⟩
    

Proof state:
case mp.mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝ Z : C
f✝ f : Y✝ ⟶ X
Y : C
⊢ f = f

Next tactic:
rfl
@[simp]
theorem singleton_eq_iff_domain (f g : Y ⟶ X) : singleton f g ↔ f = g := by
  constructor
  · rintro ⟨a, rfl⟩
    rfl
  · 

Proof state:
case mpr
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z : C
f✝ f g : Y ⟶ X
⊢ f = g → singleton f g

Next tactic:
rintro rfl
@[simp]
theorem singleton_eq_iff_domain (f g : Y ⟶ X) : singleton f g ↔ f = g := by
  constructor
  · rintro ⟨a, rfl⟩
    rfl
  · rintro rfl
    

Proof state:
case mpr
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z : C
f✝ f : Y ⟶ X
⊢ singleton f f

Next tactic:
apply singleton.mk
theorem pullback_singleton [HasPullbacks C] (g : Z ⟶ X) :
    pullbackArrows f (singleton g) = singleton (pullback.snd : pullback g f ⟶ _) := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z : C
f : Y ⟶ X
inst✝ : HasPullbacks C
g : Z ⟶ X
⊢ pullbackArrows f (singleton g) = singleton pullback.snd

Next tactic:
funext W
theorem pullback_singleton [HasPullbacks C] (g : Z ⟶ X) :
    pullbackArrows f (singleton g) = singleton (pullback.snd : pullback g f ⟶ _) := by
  funext W
  

Proof state:
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z : C
f : Y ⟶ X
inst✝ : HasPullbacks C
g : Z ⟶ X
W : C
⊢ pullbackArrows f (singleton g) = singleton pullback.snd

Next tactic:
ext h
theorem pullback_singleton [HasPullbacks C] (g : Z ⟶ X) :
    pullbackArrows f (singleton g) = singleton (pullback.snd : pullback g f ⟶ _) := by
  funext W
  ext h
  

Proof state:
case h.h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z : C
f : Y ⟶ X
inst✝ : HasPullbacks C
g : Z ⟶ X
W : C
h : W ⟶ Y
⊢ h ∈ pullbackArrows f (singleton g) ↔ h ∈ singleton pullback.snd

Next tactic:
constructor
theorem pullback_singleton [HasPullbacks C] (g : Z ⟶ X) :
    pullbackArrows f (singleton g) = singleton (pullback.snd : pullback g f ⟶ _) := by
  funext W
  ext h
  constructor
  · 

Proof state:
case h.h.mp
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z : C
f : Y ⟶ X
inst✝ : HasPullbacks C
g : Z ⟶ X
W : C
h : W ⟶ Y
⊢ h ∈ pullbackArrows f (singleton g) → h ∈ singleton pullback.snd

Next tactic:
rintro ⟨W, _, _, _⟩
theorem pullback_singleton [HasPullbacks C] (g : Z ⟶ X) :
    pullbackArrows f (singleton g) = singleton (pullback.snd : pullback g f ⟶ _) := by
  funext W
  ext h
  constructor
  · rintro ⟨W, _, _, _⟩
    

Proof state:
case h.h.mp.mk.mk
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝¹ Z : C
f : Y✝¹ ⟶ X
inst✝ : HasPullbacks C
g : Z ⟶ X
Y✝ Y : C
⊢ pullback.snd ∈ singleton pullback.snd

Next tactic:
exact singleton.mk
theorem pullback_singleton [HasPullbacks C] (g : Z ⟶ X) :
    pullbackArrows f (singleton g) = singleton (pullback.snd : pullback g f ⟶ _) := by
  funext W
  ext h
  constructor
  · rintro ⟨W, _, _, _⟩
    exact singleton.mk
  · 

Proof state:
case h.h.mpr
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z : C
f : Y ⟶ X
inst✝ : HasPullbacks C
g : Z ⟶ X
W : C
h : W ⟶ Y
⊢ h ∈ singleton pullback.snd → h ∈ pullbackArrows f (singleton g)

Next tactic:
rintro ⟨_⟩
theorem pullback_singleton [HasPullbacks C] (g : Z ⟶ X) :
    pullbackArrows f (singleton g) = singleton (pullback.snd : pullback g f ⟶ _) := by
  funext W
  ext h
  constructor
  · rintro ⟨W, _, _, _⟩
    exact singleton.mk
  · rintro ⟨_⟩
    

Proof state:
case h.h.mpr.mk
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝ Z : C
f : Y✝ ⟶ X
inst✝ : HasPullbacks C
g : Z ⟶ X
Y : C
⊢ pullback.snd ∈ pullbackArrows f (singleton g)

Next tactic:
exact pullbackArrows.mk Z g singleton.mk
theorem ofArrows_pUnit : (ofArrows _ fun _ : PUnit => f) = singleton f := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z : C
f : Y ⟶ X
⊢ (ofArrows (fun x => Y) fun x => f) = singleton f

Next tactic:
funext Y
theorem ofArrows_pUnit : (ofArrows _ fun _ : PUnit => f) = singleton f := by
  funext Y
  

Proof state:
case h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝ Z : C
f : Y✝ ⟶ X
Y : C
⊢ (ofArrows (fun x => Y✝) fun x => f) = singleton f

Next tactic:
ext g
theorem ofArrows_pUnit : (ofArrows _ fun _ : PUnit => f) = singleton f := by
  funext Y
  ext g
  

Proof state:
case h.h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝ Z : C
f : Y✝ ⟶ X
Y : C
g : Y ⟶ X
⊢ (g ∈ ofArrows (fun x => Y✝) fun x => f) ↔ g ∈ singleton f

Next tactic:
constructor
theorem ofArrows_pUnit : (ofArrows _ fun _ : PUnit => f) = singleton f := by
  funext Y
  ext g
  constructor
  · 

Proof state:
case h.h.mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝ Z : C
f : Y✝ ⟶ X
Y : C
g : Y ⟶ X
⊢ (g ∈ ofArrows (fun x => Y✝) fun x => f) → g ∈ singleton f

Next tactic:
rintro ⟨_⟩
theorem ofArrows_pUnit : (ofArrows _ fun _ : PUnit => f) = singleton f := by
  funext Y
  ext g
  constructor
  · rintro ⟨_⟩
    

Proof state:
case h.h.mp.mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝ Z : C
f : Y✝ ⟶ X
Y : C
i✝ : PUnit.{u_1 + 1}
⊢ f ∈ singleton f

Next tactic:
apply singleton.mk
theorem ofArrows_pUnit : (ofArrows _ fun _ : PUnit => f) = singleton f := by
  funext Y
  ext g
  constructor
  · rintro ⟨_⟩
    apply singleton.mk
  · 

Proof state:
case h.h.mpr
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝ Z : C
f : Y✝ ⟶ X
Y : C
g : Y ⟶ X
⊢ g ∈ singleton f → g ∈ ofArrows (fun x => Y✝) fun x => f

Next tactic:
rintro ⟨_⟩
theorem ofArrows_pUnit : (ofArrows _ fun _ : PUnit => f) = singleton f := by
  funext Y
  ext g
  constructor
  · rintro ⟨_⟩
    apply singleton.mk
  · rintro ⟨_⟩
    

Proof state:
case h.h.mpr.mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝ Z : C
f : Y✝ ⟶ X
Y : C
⊢ f ∈ ofArrows (fun x => Y✝) fun x => f

Next tactic:
exact ofArrows.mk PUnit.unit
theorem ofArrows_pullback [HasPullbacks C] {ι : Type*} (Z : ι → C) (g : ∀ i : ι, Z i ⟶ X) :
    (ofArrows (fun i => pullback (g i) f) fun i => pullback.snd) =
      pullbackArrows f (ofArrows Z g) := by
  

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z✝ : C
f : Y ⟶ X
inst✝ : HasPullbacks C
ι : Type u_1
Z : ι → C
g : (i : ι) → Z i ⟶ X
⊢ (ofArrows (fun i => pullback (g i) f) fun i => pullback.snd) = pullbackArrows f (ofArrows Z g)

Next tactic:
funext T
theorem ofArrows_pullback [HasPullbacks C] {ι : Type*} (Z : ι → C) (g : ∀ i : ι, Z i ⟶ X) :
    (ofArrows (fun i => pullback (g i) f) fun i => pullback.snd) =
      pullbackArrows f (ofArrows Z g) := by
  funext T
  

Proof state:
case h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z✝ : C
f : Y ⟶ X
inst✝ : HasPullbacks C
ι : Type u_1
Z : ι → C
g : (i : ι) → Z i ⟶ X
T : C
⊢ (ofArrows (fun i => pullback (g i) f) fun i => pullback.snd) = pullbackArrows f (ofArrows Z g)

Next tactic:
ext h
theorem ofArrows_pullback [HasPullbacks C] {ι : Type*} (Z : ι → C) (g : ∀ i : ι, Z i ⟶ X) :
    (ofArrows (fun i => pullback (g i) f) fun i => pullback.snd) =
      pullbackArrows f (ofArrows Z g) := by
  funext T
  ext h
  

Proof state:
case h.h
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z✝ : C
f : Y ⟶ X
inst✝ : HasPullbacks C
ι : Type u_1
Z : ι → C
g : (i : ι) → Z i ⟶ X
T : C
h : T ⟶ Y
⊢ (h ∈ ofArrows (fun i => pullback (g i) f) fun i => pullback.snd) ↔ h ∈ pullbackArrows f (ofArrows Z g)

Next tactic:
constructor
theorem ofArrows_pullback [HasPullbacks C] {ι : Type*} (Z : ι → C) (g : ∀ i : ι, Z i ⟶ X) :
    (ofArrows (fun i => pullback (g i) f) fun i => pullback.snd) =
      pullbackArrows f (ofArrows Z g) := by
  funext T
  ext h
  constructor
  · 

Proof state:
case h.h.mp
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z✝ : C
f : Y ⟶ X
inst✝ : HasPullbacks C
ι : Type u_1
Z : ι → C
g : (i : ι) → Z i ⟶ X
T : C
h : T ⟶ Y
⊢ (h ∈ ofArrows (fun i => pullback (g i) f) fun i => pullback.snd) → h ∈ pullbackArrows f (ofArrows Z g)

Next tactic:
rintro ⟨hk⟩
theorem ofArrows_pullback [HasPullbacks C] {ι : Type*} (Z : ι → C) (g : ∀ i : ι, Z i ⟶ X) :
    (ofArrows (fun i => pullback (g i) f) fun i => pullback.snd) =
      pullbackArrows f (ofArrows Z g) := by
  funext T
  ext h
  constructor
  · rintro ⟨hk⟩
    

Proof state:
case h.h.mp.mk
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝ Z✝ : C
f : Y✝ ⟶ X
inst✝ : HasPullbacks C
ι : Type u_1
Z : ι → C
g : (i : ι) → Z i ⟶ X
Y : C
hk : ι
⊢ pullback.snd ∈ pullbackArrows f (ofArrows Z g)

Next tactic:
exact pullbackArrows.mk _ _ (ofArrows.mk hk)
theorem ofArrows_pullback [HasPullbacks C] {ι : Type*} (Z : ι → C) (g : ∀ i : ι, Z i ⟶ X) :
    (ofArrows (fun i => pullback (g i) f) fun i => pullback.snd) =
      pullbackArrows f (ofArrows Z g) := by
  funext T
  ext h
  constructor
  · rintro ⟨hk⟩
    exact pullbackArrows.mk _ _ (ofArrows.mk hk)
  · 

Proof state:
case h.h.mpr
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z✝ : C
f : Y ⟶ X
inst✝ : HasPullbacks C
ι : Type u_1
Z : ι → C
g : (i : ι) → Z i ⟶ X
T : C
h : T ⟶ Y
⊢ h ∈ pullbackArrows f (ofArrows Z g) → h ∈ ofArrows (fun i => pullback (g i) f) fun i => pullback.snd

Next tactic:
rintro ⟨W, k, hk₁⟩
theorem ofArrows_pullback [HasPullbacks C] {ι : Type*} (Z : ι → C) (g : ∀ i : ι, Z i ⟶ X) :
    (ofArrows (fun i => pullback (g i) f) fun i => pullback.snd) =
      pullbackArrows f (ofArrows Z g) := by
  funext T
  ext h
  constructor
  · rintro ⟨hk⟩
    exact pullbackArrows.mk _ _ (ofArrows.mk hk)
  · rintro ⟨W, k, hk₁⟩
    

Proof state:
case h.h.mpr.mk
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝ Z✝ : C
f : Y✝ ⟶ X
inst✝ : HasPullbacks C
ι : Type u_1
Z : ι → C
g : (i : ι) → Z i ⟶ X
Y W : C
k : W ⟶ X
hk₁ : ofArrows Z g k
⊢ pullback.snd ∈ ofArrows (fun i => pullback (g i) f) fun i => pullback.snd

Next tactic:
cases' hk₁ with i hi
theorem ofArrows_pullback [HasPullbacks C] {ι : Type*} (Z : ι → C) (g : ∀ i : ι, Z i ⟶ X) :
    (ofArrows (fun i => pullback (g i) f) fun i => pullback.snd) =
      pullbackArrows f (ofArrows Z g) := by
  funext T
  ext h
  constructor
  · rintro ⟨hk⟩
    exact pullbackArrows.mk _ _ (ofArrows.mk hk)
  · rintro ⟨W, k, hk₁⟩
    cases' hk₁ with i hi
    

Proof state:
case h.h.mpr.mk.mk
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝ Z✝ : C
f : Y✝ ⟶ X
inst✝ : HasPullbacks C
ι : Type u_1
Z : ι → C
g : (i : ι) → Z i ⟶ X
Y : C
i : ι
⊢ pullback.snd ∈ ofArrows (fun i => pullback (g i) f) fun i => pullback.snd

Next tactic:
apply ofArrows.mk
theorem ofArrows_bind {ι : Type*} (Z : ι → C) (g : ∀ i : ι, Z i ⟶ X)
    (j : ∀ ⦃Y⦄ (f : Y ⟶ X), ofArrows Z g f → Type*) (W : ∀ ⦃Y⦄ (f : Y ⟶ X) (H), j f H → C)
    (k : ∀ ⦃Y⦄ (f : Y ⟶ X) (H i), W f H i ⟶ Y) :
    ((ofArrows Z g).bind fun Y f H => ofArrows (W f H) (k f H)) =
      ofArrows (fun i : Σi, j _ (ofArrows.mk i) => W (g i.1) _ i.2) fun ij =>
        k (g ij.1) _ ij.2 ≫ g ij.1 := by
  

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y Z✝ : C
f : Y ⟶ X
ι : Type u_1
Z : ι → C
g : (i : ι) → Z i ⟶ X
j : ⦃Y : C⦄ → (f : Y ⟶ X) → ofArrows Z g f → Type u_2
W : ⦃Y : C⦄ → (f : Y ⟶ X) → (H : ofArrows Z g f) → j f H → C
k : ⦃Y : C⦄ → (f : Y ⟶ X) → (H : ofArrows Z g f) → (i : j f H) → W f H i ⟶ Y
⊢ (bind (ofArrows Z g) fun Y f H => ofArrows (W f H) (k f H)) =
    ofArrows (fun i => W (g i.fst) (_ : ofArrows Z g (g i.fst)) i.snd) fun ij =>
      k (g ij.fst) (_ : ofArrows Z g (g ij.fst)) ij.snd ≫ g ij.fst

Next tactic:
funext Y
theorem ofArrows_bind {ι : Type*} (Z : ι → C) (g : ∀ i : ι, Z i ⟶ X)
    (j : ∀ ⦃Y⦄ (f : Y ⟶ X), ofArrows Z g f → Type*) (W : ∀ ⦃Y⦄ (f : Y ⟶ X) (H), j f H → C)
    (k : ∀ ⦃Y⦄ (f : Y ⟶ X) (H i), W f H i ⟶ Y) :
    ((ofArrows Z g).bind fun Y f H => ofArrows (W f H) (k f H)) =
      ofArrows (fun i : Σi, j _ (ofArrows.mk i) => W (g i.1) _ i.2) fun ij =>
        k (g ij.1) _ ij.2 ≫ g ij.1 := by
  funext Y
  

Proof state:
case h
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
F : C ⥤ D
X Y✝ Z✝ : C
f : Y✝ ⟶ X
ι : Type u_1
Z : ι → C
g : (i : ι) → Z i ⟶ X
j : ⦃Y : C⦄ → (f : Y ⟶ X) → ofArrows Z g f → Type u_2
W : ⦃Y : C⦄ → (f : Y ⟶ X) → (H : ofArrows Z g f) → j f H → C
k : ⦃Y : C⦄ → (f : Y ⟶ X) → (H : ofArrows Z g f) → (i : j f H) → W f H i ⟶ Y
Y : C
⊢ (bind (ofArrows Z g) fun Y f H => ofArrows (W f H) (k f H)) =
    ofArrows (fun i => W (g i.fst) (_ : ofArrows Z g (g i.fst)) i.snd) fun ij =>
      k (g ij.fst) (_ : ofArrows Z g (g ij.fst)) ij.snd ≫ g ij.fst

Next tactic:
ext f