l3lab/ntp-mathlib huggingface dataset:
/-- A functor that preserves pushouts and binary coproducts also presrves coequalizers. -/
def preservesCoequalizersOfPreservesPushoutsAndBinaryCoproducts [HasBinaryCoproducts C]
    [HasPushouts C] [PreservesColimitsOfShape (Discrete WalkingPair) G]
    [PreservesColimitsOfShape WalkingSpan G] : PreservesColimitsOfShape WalkingParallelPair G :=
  ⟨fun {K} =>
    preservesColimitOfPreservesColimitCocone (coequalizerCoconeIsColimit K) <|
      { desc := fun c => by
          refine' (PreservesPushout.iso _ _ _).inv ≫ pushout.desc _ _ _
          · exact c.ι.app WalkingParallelPair.one
          · exact c.ι.app WalkingParallelPair.one
          apply (mapIsColimitOfPreservesOfIsColimit G _ _ (coprodIsCoprod _ _)).hom_ext
          rintro (_ | _)
          · simp only [BinaryCofan.ι_app_left, BinaryCofan.mk_inl, Category.assoc, ←
              G.map_comp_assoc, coprod.inl_desc]
          · simp only [BinaryCofan.ι_app_right, BinaryCofan.mk_inr, Category.assoc, ←
              G.map_comp_assoc, coprod.inr_desc]
            exact
              (c.ι.naturality WalkingParallelPairHom.left).trans
                (c.ι.naturality WalkingParallelPairHom.right).symm
        fac := fun c j => by
          rcases j with (_ | _) <;>
            simp only [Functor.mapCocone_ι_app, Cocone.ofCofork_ι, Category.id_comp,
              eqToHom_refl, Category.assoc, Functor.map_comp, Cofork.ofπ_ι_app, pushout.inl_desc,
              PreservesPushout.inl_iso_inv_assoc]
          exact (c.ι.naturality WalkingParallelPairHom.left).trans (Category.comp_id _)
        uniq := fun s m h => by
          rw [Iso.eq_inv_comp]
          have := h WalkingParallelPair.one
          dsimp [coequalizerCocone] at this
          ext <;>
            

Proof state:
case h₁
C : Type u
inst✝⁵ : Category.{v, u} C
D : Type u'
inst✝⁴ : Category.{v', u'} D
G : C ⥤ D
inst✝³ : HasBinaryCoproducts C
inst✝² : HasPushouts C
inst✝¹ : PreservesColimitsOfShape (Discrete WalkingPair) G
inst✝ : PreservesColimitsOfShape WalkingSpan G
K : WalkingParallelPair ⥤ C
s : Cocone (K ⋙ G)
m : (G.mapCocone (coequalizerCocone K)).pt ⟶ s.pt
h : ∀ (j : WalkingParallelPair), (G.mapCocone (coequalizerCocone K)).ι.app j ≫ m = s.ι.app j
this : G.map (𝟙 (K.obj WalkingParallelPair.one) ≫ pushoutInl K) ≫ m = s.ι.app WalkingParallelPair.one
⊢ pushout.inr ≫
      (PreservesPushout.iso G (coprod.desc (𝟙 (K.obj WalkingParallelPair.one)) (K.map WalkingParallelPairHom.left))
            (coprod.desc (𝟙 (K.obj WalkingParallelPair.one)) (K.map WalkingParallelPairHom.right))).hom ≫
        m =
    pushout.inr ≫
      pushout.desc (s.ι.app WalkingParallelPair.one) (s.ι.app WalkingParallelPair.one)
        (_ :
          G.map (coprod.desc (𝟙 (K.obj WalkingParallelPair.one)) (K.map WalkingParallelPairHom.left)) ≫
              s.ι.app WalkingParallelPair.one =
            G.map (coprod.desc (𝟙 (K.obj WalkingParallelPair.one)) (K.map WalkingParallelPairHom.right)) ≫
              s.ι.app WalkingParallelPair.one)

Next tactic:
simp only [PreservesPushout.inl_iso_hom_assoc, Category.id_comp, pushout.inl_desc,
              pushout.inr_desc, PreservesPushout.inr_iso_hom_assoc, ← pushoutInl_eq_pushout_inr, ←
              this]
/-- An auxiliary function for `Quotient.finChoice`.  Given a
collection of setoids indexed by a type `ι`, a (finite) list `l` of
indices, and a function that for each `i ∈ l` gives a term of the
corresponding quotient type, then there is a corresponding term in the
quotient of the product of the setoids indexed by `l`. -/
def Quotient.finChoiceAux {ι : Type*} [DecidableEq ι] {α : ι → Type*} [S : ∀ i, Setoid (α i)] :
    ∀ l : List ι, (∀ i ∈ l, Quotient (S i)) → @Quotient (∀ i ∈ l, α i) (by 

Proof state:
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
l : List ι
⊢ Setoid ((i : ι) → i ∈ l → α i)

Next tactic:
infer_instance
/-- An auxiliary function for `Quotient.finChoice`.  Given a
collection of setoids indexed by a type `ι`, a (finite) list `l` of
indices, and a function that for each `i ∈ l` gives a term of the
corresponding quotient type, then there is a corresponding term in the
quotient of the product of the setoids indexed by `l`. -/
def Quotient.finChoiceAux {ι : Type*} [DecidableEq ι] {α : ι → Type*} [S : ∀ i, Setoid (α i)] :
    ∀ l : List ι, (∀ i ∈ l, Quotient (S i)) → @Quotient (∀ i ∈ l, α i) (by infer_instance)
  | [], _ => ⟦fun i h => nomatch List.not_mem_nil _ h⟧
  | i :: l, f => by
    

Proof state:
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → Quotient (S i_1)
⊢ Quotient inferInstance

Next tactic:
refine'
      Quotient.liftOn₂ (f i (List.mem_cons_self _ _))
        (Quotient.finChoiceAux l fun j h => f j (List.mem_cons_of_mem _ h)) _ _
/-- An auxiliary function for `Quotient.finChoice`.  Given a
collection of setoids indexed by a type `ι`, a (finite) list `l` of
indices, and a function that for each `i ∈ l` gives a term of the
corresponding quotient type, then there is a corresponding term in the
quotient of the product of the setoids indexed by `l`. -/
def Quotient.finChoiceAux {ι : Type*} [DecidableEq ι] {α : ι → Type*} [S : ∀ i, Setoid (α i)] :
    ∀ l : List ι, (∀ i ∈ l, Quotient (S i)) → @Quotient (∀ i ∈ l, α i) (by infer_instance)
  | [], _ => ⟦fun i h => nomatch List.not_mem_nil _ h⟧
  | i :: l, f => by
    refine'
      Quotient.liftOn₂ (f i (List.mem_cons_self _ _))
        (Quotient.finChoiceAux l fun j h => f j (List.mem_cons_of_mem _ h)) _ _
    

Proof state:
case refine'_1
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → Quotient (S i_1)
⊢ α i → ((i : ι) → i ∈ l → α i) → Quotient inferInstance
case refine'_2
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → Quotient (S i_1)
⊢ ∀ (a₁ : α i) (b₁ : (i : ι) → i ∈ l → α i) (a₂ : α i) (b₂ : (i : ι) → i ∈ l → α i),
    a₁ ≈ a₂ → b₁ ≈ b₂ → ?refine'_1 a₁ b₁ = ?refine'_1 a₂ b₂

Next tactic:
exact fun a l => ⟦fun j h =>
      if e : j = i then by rw [e]; exact a else l _ ((List.mem_cons.1 h).resolve_left e)⟧
/-- An auxiliary function for `Quotient.finChoice`.  Given a
collection of setoids indexed by a type `ι`, a (finite) list `l` of
indices, and a function that for each `i ∈ l` gives a term of the
corresponding quotient type, then there is a corresponding term in the
quotient of the product of the setoids indexed by `l`. -/
def Quotient.finChoiceAux {ι : Type*} [DecidableEq ι] {α : ι → Type*} [S : ∀ i, Setoid (α i)] :
    ∀ l : List ι, (∀ i ∈ l, Quotient (S i)) → @Quotient (∀ i ∈ l, α i) (by infer_instance)
  | [], _ => ⟦fun i h => nomatch List.not_mem_nil _ h⟧
  | i :: l, f => by
    refine'
      Quotient.liftOn₂ (f i (List.mem_cons_self _ _))
        (Quotient.finChoiceAux l fun j h => f j (List.mem_cons_of_mem _ h)) _ _
    exact fun a l => ⟦fun j h =>
      if e : j = i then by 

Proof state:
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l✝ : List ι
f : (i_1 : ι) → i_1 ∈ i :: l✝ → Quotient (S i_1)
a : α i
l : (i : ι) → i ∈ l✝ → α i
j : ι
h : j ∈ i :: l✝
e : j = i
⊢ α j

Next tactic:
rw [e]
/-- An auxiliary function for `Quotient.finChoice`.  Given a
collection of setoids indexed by a type `ι`, a (finite) list `l` of
indices, and a function that for each `i ∈ l` gives a term of the
corresponding quotient type, then there is a corresponding term in the
quotient of the product of the setoids indexed by `l`. -/
def Quotient.finChoiceAux {ι : Type*} [DecidableEq ι] {α : ι → Type*} [S : ∀ i, Setoid (α i)] :
    ∀ l : List ι, (∀ i ∈ l, Quotient (S i)) → @Quotient (∀ i ∈ l, α i) (by infer_instance)
  | [], _ => ⟦fun i h => nomatch List.not_mem_nil _ h⟧
  | i :: l, f => by
    refine'
      Quotient.liftOn₂ (f i (List.mem_cons_self _ _))
        (Quotient.finChoiceAux l fun j h => f j (List.mem_cons_of_mem _ h)) _ _
    exact fun a l => ⟦fun j h =>
      if e : j = i then by rw [e]; 

Proof state:
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l✝ : List ι
f : (i_1 : ι) → i_1 ∈ i :: l✝ → Quotient (S i_1)
a : α i
l : (i : ι) → i ∈ l✝ → α i
j : ι
h : j ∈ i :: l✝
e : j = i
⊢ α i

Next tactic:
exact a
/-- An auxiliary function for `Quotient.finChoice`.  Given a
collection of setoids indexed by a type `ι`, a (finite) list `l` of
indices, and a function that for each `i ∈ l` gives a term of the
corresponding quotient type, then there is a corresponding term in the
quotient of the product of the setoids indexed by `l`. -/
def Quotient.finChoiceAux {ι : Type*} [DecidableEq ι] {α : ι → Type*} [S : ∀ i, Setoid (α i)] :
    ∀ l : List ι, (∀ i ∈ l, Quotient (S i)) → @Quotient (∀ i ∈ l, α i) (by infer_instance)
  | [], _ => ⟦fun i h => nomatch List.not_mem_nil _ h⟧
  | i :: l, f => by
    refine'
      Quotient.liftOn₂ (f i (List.mem_cons_self _ _))
        (Quotient.finChoiceAux l fun j h => f j (List.mem_cons_of_mem _ h)) _ _
    exact fun a l => ⟦fun j h =>
      if e : j = i then by rw [e]; exact a else l _ ((List.mem_cons.1 h).resolve_left e)⟧
    

Proof state:
case refine'_2
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → Quotient (S i_1)
⊢ ∀ (a₁ : α i) (b₁ : (i : ι) → i ∈ l → α i) (a₂ : α i) (b₂ : (i : ι) → i ∈ l → α i),
    a₁ ≈ a₂ →
      b₁ ≈ b₂ →
        ⟦fun j h => if e : j = i then Eq.mpr (_ : α j = α i) a₁ else b₁ j (_ : j ∈ l)⟧ =
          ⟦fun j h => if e : j = i then Eq.mpr (_ : α j = α i) a₂ else b₂ j (_ : j ∈ l)⟧

Next tactic:
refine' fun a₁ l₁ a₂ l₂ h₁ h₂ => Quotient.sound fun j h => _
/-- An auxiliary function for `Quotient.finChoice`.  Given a
collection of setoids indexed by a type `ι`, a (finite) list `l` of
indices, and a function that for each `i ∈ l` gives a term of the
corresponding quotient type, then there is a corresponding term in the
quotient of the product of the setoids indexed by `l`. -/
def Quotient.finChoiceAux {ι : Type*} [DecidableEq ι] {α : ι → Type*} [S : ∀ i, Setoid (α i)] :
    ∀ l : List ι, (∀ i ∈ l, Quotient (S i)) → @Quotient (∀ i ∈ l, α i) (by infer_instance)
  | [], _ => ⟦fun i h => nomatch List.not_mem_nil _ h⟧
  | i :: l, f => by
    refine'
      Quotient.liftOn₂ (f i (List.mem_cons_self _ _))
        (Quotient.finChoiceAux l fun j h => f j (List.mem_cons_of_mem _ h)) _ _
    exact fun a l => ⟦fun j h =>
      if e : j = i then by rw [e]; exact a else l _ ((List.mem_cons.1 h).resolve_left e)⟧
    refine' fun a₁ l₁ a₂ l₂ h₁ h₂ => Quotient.sound fun j h => _
    

Proof state:
case refine'_2
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → Quotient (S i_1)
a₁ : α i
l₁ : (i : ι) → i ∈ l → α i
a₂ : α i
l₂ : (i : ι) → i ∈ l → α i
h₁ : a₁ ≈ a₂
h₂ : l₁ ≈ l₂
j : ι
h : j ∈ i :: l
⊢ (if e : j = i then Eq.mpr (_ : α j = α i) a₁ else l₁ j (_ : j ∈ l)) ≈
    if e : j = i then Eq.mpr (_ : α j = α i) a₂ else l₂ j (_ : j ∈ l)

Next tactic:
by_cases e : j = i
/-- An auxiliary function for `Quotient.finChoice`.  Given a
collection of setoids indexed by a type `ι`, a (finite) list `l` of
indices, and a function that for each `i ∈ l` gives a term of the
corresponding quotient type, then there is a corresponding term in the
quotient of the product of the setoids indexed by `l`. -/
def Quotient.finChoiceAux {ι : Type*} [DecidableEq ι] {α : ι → Type*} [S : ∀ i, Setoid (α i)] :
    ∀ l : List ι, (∀ i ∈ l, Quotient (S i)) → @Quotient (∀ i ∈ l, α i) (by infer_instance)
  | [], _ => ⟦fun i h => nomatch List.not_mem_nil _ h⟧
  | i :: l, f => by
    refine'
      Quotient.liftOn₂ (f i (List.mem_cons_self _ _))
        (Quotient.finChoiceAux l fun j h => f j (List.mem_cons_of_mem _ h)) _ _
    exact fun a l => ⟦fun j h =>
      if e : j = i then by rw [e]; exact a else l _ ((List.mem_cons.1 h).resolve_left e)⟧
    refine' fun a₁ l₁ a₂ l₂ h₁ h₂ => Quotient.sound fun j h => _
    by_cases e : j = i <;> 

Proof state:
case pos
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → Quotient (S i_1)
a₁ : α i
l₁ : (i : ι) → i ∈ l → α i
a₂ : α i
l₂ : (i : ι) → i ∈ l → α i
h₁ : a₁ ≈ a₂
h₂ : l₁ ≈ l₂
j : ι
h : j ∈ i :: l
e : j = i
⊢ (if e : j = i then Eq.mpr (_ : α j = α i) a₁ else l₁ j (_ : j ∈ l)) ≈
    if e : j = i then Eq.mpr (_ : α j = α i) a₂ else l₂ j (_ : j ∈ l)

Next tactic:
simp [e]
/-- An auxiliary function for `Quotient.finChoice`.  Given a
collection of setoids indexed by a type `ι`, a (finite) list `l` of
indices, and a function that for each `i ∈ l` gives a term of the
corresponding quotient type, then there is a corresponding term in the
quotient of the product of the setoids indexed by `l`. -/
def Quotient.finChoiceAux {ι : Type*} [DecidableEq ι] {α : ι → Type*} [S : ∀ i, Setoid (α i)] :
    ∀ l : List ι, (∀ i ∈ l, Quotient (S i)) → @Quotient (∀ i ∈ l, α i) (by infer_instance)
  | [], _ => ⟦fun i h => nomatch List.not_mem_nil _ h⟧
  | i :: l, f => by
    refine'
      Quotient.liftOn₂ (f i (List.mem_cons_self _ _))
        (Quotient.finChoiceAux l fun j h => f j (List.mem_cons_of_mem _ h)) _ _
    exact fun a l => ⟦fun j h =>
      if e : j = i then by rw [e]; exact a else l _ ((List.mem_cons.1 h).resolve_left e)⟧
    refine' fun a₁ l₁ a₂ l₂ h₁ h₂ => Quotient.sound fun j h => _
    by_cases e : j = i <;> 

Proof state:
case neg
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → Quotient (S i_1)
a₁ : α i
l₁ : (i : ι) → i ∈ l → α i
a₂ : α i
l₂ : (i : ι) → i ∈ l → α i
h₁ : a₁ ≈ a₂
h₂ : l₁ ≈ l₂
j : ι
h : j ∈ i :: l
e : ¬j = i
⊢ (if e : j = i then Eq.mpr (_ : α j = α i) a₁ else l₁ j (_ : j ∈ l)) ≈
    if e : j = i then Eq.mpr (_ : α j = α i) a₂ else l₂ j (_ : j ∈ l)

Next tactic:
simp [e]
/-- An auxiliary function for `Quotient.finChoice`.  Given a
collection of setoids indexed by a type `ι`, a (finite) list `l` of
indices, and a function that for each `i ∈ l` gives a term of the
corresponding quotient type, then there is a corresponding term in the
quotient of the product of the setoids indexed by `l`. -/
def Quotient.finChoiceAux {ι : Type*} [DecidableEq ι] {α : ι → Type*} [S : ∀ i, Setoid (α i)] :
    ∀ l : List ι, (∀ i ∈ l, Quotient (S i)) → @Quotient (∀ i ∈ l, α i) (by infer_instance)
  | [], _ => ⟦fun i h => nomatch List.not_mem_nil _ h⟧
  | i :: l, f => by
    refine'
      Quotient.liftOn₂ (f i (List.mem_cons_self _ _))
        (Quotient.finChoiceAux l fun j h => f j (List.mem_cons_of_mem _ h)) _ _
    exact fun a l => ⟦fun j h =>
      if e : j = i then by rw [e]; exact a else l _ ((List.mem_cons.1 h).resolve_left e)⟧
    refine' fun a₁ l₁ a₂ l₂ h₁ h₂ => Quotient.sound fun j h => _
    by_cases e : j = i <;> simp [e]
    · 

Proof state:
case pos
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → Quotient (S i_1)
a₁ : α i
l₁ : (i : ι) → i ∈ l → α i
a₂ : α i
l₂ : (i : ι) → i ∈ l → α i
h₁ : a₁ ≈ a₂
h₂ : l₁ ≈ l₂
j : ι
h : j ∈ i :: l
e : j = i
⊢ cast (_ : α i = α j) a₁ ≈ cast (_ : α i = α j) a₂

Next tactic:
subst j
/-- An auxiliary function for `Quotient.finChoice`.  Given a
collection of setoids indexed by a type `ι`, a (finite) list `l` of
indices, and a function that for each `i ∈ l` gives a term of the
corresponding quotient type, then there is a corresponding term in the
quotient of the product of the setoids indexed by `l`. -/
def Quotient.finChoiceAux {ι : Type*} [DecidableEq ι] {α : ι → Type*} [S : ∀ i, Setoid (α i)] :
    ∀ l : List ι, (∀ i ∈ l, Quotient (S i)) → @Quotient (∀ i ∈ l, α i) (by infer_instance)
  | [], _ => ⟦fun i h => nomatch List.not_mem_nil _ h⟧
  | i :: l, f => by
    refine'
      Quotient.liftOn₂ (f i (List.mem_cons_self _ _))
        (Quotient.finChoiceAux l fun j h => f j (List.mem_cons_of_mem _ h)) _ _
    exact fun a l => ⟦fun j h =>
      if e : j = i then by rw [e]; exact a else l _ ((List.mem_cons.1 h).resolve_left e)⟧
    refine' fun a₁ l₁ a₂ l₂ h₁ h₂ => Quotient.sound fun j h => _
    by_cases e : j = i <;> simp [e]
    · subst j
      

Proof state:
case pos
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → Quotient (S i_1)
a₁ : α i
l₁ : (i : ι) → i ∈ l → α i
a₂ : α i
l₂ : (i : ι) → i ∈ l → α i
h₁ : a₁ ≈ a₂
h₂ : l₁ ≈ l₂
h : i ∈ i :: l
⊢ cast (_ : α i = α i) a₁ ≈ cast (_ : α i = α i) a₂

Next tactic:
exact h₁
/-- An auxiliary function for `Quotient.finChoice`.  Given a
collection of setoids indexed by a type `ι`, a (finite) list `l` of
indices, and a function that for each `i ∈ l` gives a term of the
corresponding quotient type, then there is a corresponding term in the
quotient of the product of the setoids indexed by `l`. -/
def Quotient.finChoiceAux {ι : Type*} [DecidableEq ι] {α : ι → Type*} [S : ∀ i, Setoid (α i)] :
    ∀ l : List ι, (∀ i ∈ l, Quotient (S i)) → @Quotient (∀ i ∈ l, α i) (by infer_instance)
  | [], _ => ⟦fun i h => nomatch List.not_mem_nil _ h⟧
  | i :: l, f => by
    refine'
      Quotient.liftOn₂ (f i (List.mem_cons_self _ _))
        (Quotient.finChoiceAux l fun j h => f j (List.mem_cons_of_mem _ h)) _ _
    exact fun a l => ⟦fun j h =>
      if e : j = i then by rw [e]; exact a else l _ ((List.mem_cons.1 h).resolve_left e)⟧
    refine' fun a₁ l₁ a₂ l₂ h₁ h₂ => Quotient.sound fun j h => _
    by_cases e : j = i <;> simp [e]
    · subst j
      exact h₁
    · 

Proof state:
case neg
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → Quotient (S i_1)
a₁ : α i
l₁ : (i : ι) → i ∈ l → α i
a₂ : α i
l₂ : (i : ι) → i ∈ l → α i
h₁ : a₁ ≈ a₂
h₂ : l₁ ≈ l₂
j : ι
h : j ∈ i :: l
e : ¬j = i
⊢ l₁ j (_ : j ∈ l) ≈ l₂ j (_ : j ∈ l)

Next tactic:
exact h₂ _ _
theorem Quotient.finChoiceAux_eq {ι : Type*} [DecidableEq ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] :
    ∀ (l : List ι) (f : ∀ i ∈ l, α i), (Quotient.finChoiceAux l fun i h => ⟦f i h⟧) = ⟦f⟧
  | [], f => Quotient.sound fun i h => nomatch List.not_mem_nil _ h
  | i :: l, f => by
    

Proof state:
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → α i_1
⊢ (finChoiceAux (i :: l) fun i_1 h => ⟦f i_1 h⟧) = ⟦f⟧

Next tactic:
simp only [finChoiceAux, Quotient.finChoiceAux_eq l, eq_mpr_eq_cast, lift_mk]
theorem Quotient.finChoiceAux_eq {ι : Type*} [DecidableEq ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] :
    ∀ (l : List ι) (f : ∀ i ∈ l, α i), (Quotient.finChoiceAux l fun i h => ⟦f i h⟧) = ⟦f⟧
  | [], f => Quotient.sound fun i h => nomatch List.not_mem_nil _ h
  | i :: l, f => by
    simp only [finChoiceAux, Quotient.finChoiceAux_eq l, eq_mpr_eq_cast, lift_mk]
    

Proof state:
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → α i_1
⊢ ⟦fun j h =>
      if h : j = i then cast (_ : (fun i => α i) i = (fun i => α i) j) (f i (_ : i ∈ i :: l))
      else f j (_ : j ∈ i :: l)⟧ =
    ⟦f⟧

Next tactic:
refine' Quotient.sound fun j h => _
theorem Quotient.finChoiceAux_eq {ι : Type*} [DecidableEq ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] :
    ∀ (l : List ι) (f : ∀ i ∈ l, α i), (Quotient.finChoiceAux l fun i h => ⟦f i h⟧) = ⟦f⟧
  | [], f => Quotient.sound fun i h => nomatch List.not_mem_nil _ h
  | i :: l, f => by
    simp only [finChoiceAux, Quotient.finChoiceAux_eq l, eq_mpr_eq_cast, lift_mk]
    refine' Quotient.sound fun j h => _
    

Proof state:
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → α i_1
j : ι
h : j ∈ i :: l
⊢ (if h : j = i then cast (_ : (fun i => α i) i = (fun i => α i) j) (f i (_ : i ∈ i :: l)) else f j (_ : j ∈ i :: l)) ≈
    f j h

Next tactic:
by_cases e : j = i
theorem Quotient.finChoiceAux_eq {ι : Type*} [DecidableEq ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] :
    ∀ (l : List ι) (f : ∀ i ∈ l, α i), (Quotient.finChoiceAux l fun i h => ⟦f i h⟧) = ⟦f⟧
  | [], f => Quotient.sound fun i h => nomatch List.not_mem_nil _ h
  | i :: l, f => by
    simp only [finChoiceAux, Quotient.finChoiceAux_eq l, eq_mpr_eq_cast, lift_mk]
    refine' Quotient.sound fun j h => _
    by_cases e : j = i <;> 

Proof state:
case pos
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → α i_1
j : ι
h : j ∈ i :: l
e : j = i
⊢ (if h : j = i then cast (_ : (fun i => α i) i = (fun i => α i) j) (f i (_ : i ∈ i :: l)) else f j (_ : j ∈ i :: l)) ≈
    f j h

Next tactic:
simp [e]
theorem Quotient.finChoiceAux_eq {ι : Type*} [DecidableEq ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] :
    ∀ (l : List ι) (f : ∀ i ∈ l, α i), (Quotient.finChoiceAux l fun i h => ⟦f i h⟧) = ⟦f⟧
  | [], f => Quotient.sound fun i h => nomatch List.not_mem_nil _ h
  | i :: l, f => by
    simp only [finChoiceAux, Quotient.finChoiceAux_eq l, eq_mpr_eq_cast, lift_mk]
    refine' Quotient.sound fun j h => _
    by_cases e : j = i <;> 

Proof state:
case neg
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → α i_1
j : ι
h : j ∈ i :: l
e : ¬j = i
⊢ (if h : j = i then cast (_ : (fun i => α i) i = (fun i => α i) j) (f i (_ : i ∈ i :: l)) else f j (_ : j ∈ i :: l)) ≈
    f j h

Next tactic:
simp [e]
theorem Quotient.finChoiceAux_eq {ι : Type*} [DecidableEq ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] :
    ∀ (l : List ι) (f : ∀ i ∈ l, α i), (Quotient.finChoiceAux l fun i h => ⟦f i h⟧) = ⟦f⟧
  | [], f => Quotient.sound fun i h => nomatch List.not_mem_nil _ h
  | i :: l, f => by
    simp only [finChoiceAux, Quotient.finChoiceAux_eq l, eq_mpr_eq_cast, lift_mk]
    refine' Quotient.sound fun j h => _
    by_cases e : j = i <;> simp [e] <;> 

Proof state:
case pos
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → α i_1
j : ι
h : j ∈ i :: l
e : j = i
⊢ cast (_ : (fun i => α i) i = (fun i => α i) j) (f i (_ : i ∈ i :: l)) ≈ f j h

Next tactic:
try exact Setoid.refl _
theorem Quotient.finChoiceAux_eq {ι : Type*} [DecidableEq ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] :
    ∀ (l : List ι) (f : ∀ i ∈ l, α i), (Quotient.finChoiceAux l fun i h => ⟦f i h⟧) = ⟦f⟧
  | [], f => Quotient.sound fun i h => nomatch List.not_mem_nil _ h
  | i :: l, f => by
    simp only [finChoiceAux, Quotient.finChoiceAux_eq l, eq_mpr_eq_cast, lift_mk]
    refine' Quotient.sound fun j h => _
    by_cases e : j = i <;> simp [e] <;> try 

Proof state:
case pos
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → α i_1
j : ι
h : j ∈ i :: l
e : j = i
⊢ cast (_ : (fun i => α i) i = (fun i => α i) j) (f i (_ : i ∈ i :: l)) ≈ f j h

Next tactic:
exact Setoid.refl _
theorem Quotient.finChoiceAux_eq {ι : Type*} [DecidableEq ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] :
    ∀ (l : List ι) (f : ∀ i ∈ l, α i), (Quotient.finChoiceAux l fun i h => ⟦f i h⟧) = ⟦f⟧
  | [], f => Quotient.sound fun i h => nomatch List.not_mem_nil _ h
  | i :: l, f => by
    simp only [finChoiceAux, Quotient.finChoiceAux_eq l, eq_mpr_eq_cast, lift_mk]
    refine' Quotient.sound fun j h => _
    by_cases e : j = i <;> simp [e] <;> 

Proof state:
case neg
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → α i_1
j : ι
h : j ∈ i :: l
e : ¬j = i
⊢ f j (_ : j ∈ i :: l) ≈ f j h

Next tactic:
try exact Setoid.refl _
theorem Quotient.finChoiceAux_eq {ι : Type*} [DecidableEq ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] :
    ∀ (l : List ι) (f : ∀ i ∈ l, α i), (Quotient.finChoiceAux l fun i h => ⟦f i h⟧) = ⟦f⟧
  | [], f => Quotient.sound fun i h => nomatch List.not_mem_nil _ h
  | i :: l, f => by
    simp only [finChoiceAux, Quotient.finChoiceAux_eq l, eq_mpr_eq_cast, lift_mk]
    refine' Quotient.sound fun j h => _
    by_cases e : j = i <;> simp [e] <;> try 

Proof state:
case neg
ι : Type u_1
inst✝ : DecidableEq ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
i : ι
l : List ι
f : (i_1 : ι) → i_1 ∈ i :: l → α i_1
j : ι
h : j ∈ i :: l
e : ¬j = i
⊢ f j (_ : j ∈ i :: l) ≈ f j h

Next tactic:
exact Setoid.refl _