l3lab/ntp-mathlib huggingface dataset:
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 exact Setoid.refl _
    

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:
subst j
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 exact Setoid.refl _
    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 → α i_1
h : i ∈ i :: l
⊢ cast (_ : (fun i => α i) i = (fun i => α i) i) (f i (_ : i ∈ i :: l)) ≈ f i h

Next tactic:
exact Setoid.refl _
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by 

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
⊢ Setoid ((i : ι) → α i)

Next tactic:
infer_instance
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by 

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
l : Multiset ι
⊢ Setoid ((i : ι) → i ∈ l → α i)

Next tactic:
infer_instance
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : List ι
h : a ≈ b
⊢ (_ : ⟦a⟧ = ⟦b⟧) ▸ (fun l => finChoiceAux l fun i x => f i) a = (fun l => finChoiceAux l fun i x => f i) b

Next tactic:
have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : List ι
h : a ≈ b
this : ∀ (a : List ι), (finChoiceAux a fun i h => ⟦out (f i)⟧) = ⟦fun i x => out (f i)⟧
⊢ (_ : ⟦a⟧ = ⟦b⟧) ▸ (fun l => finChoiceAux l fun i x => f i) a = (fun l => finChoiceAux l fun i x => f i) b

Next tactic:
simp? [Quotient.out_eq] at this says simp only [out_eq] at this
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      simp? [Quotient.out_eq] at this says 

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : List ι
h : a ≈ b
this : ∀ (a : List ι), (finChoiceAux a fun i h => ⟦out (f i)⟧) = ⟦fun i x => out (f i)⟧
⊢ (_ : ⟦a⟧ = ⟦b⟧) ▸ (fun l => finChoiceAux l fun i x => f i) a = (fun l => finChoiceAux l fun i x => f i) b

Next tactic:
simp only [out_eq] at this
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      simp? [Quotient.out_eq] at this says simp only [out_eq] at this
      

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : List ι
h : a ≈ b
this : ∀ (a : List ι), (finChoiceAux a fun i h => f i) = ⟦fun i x => out (f i)⟧
⊢ (_ : ⟦a⟧ = ⟦b⟧) ▸ (fun l => finChoiceAux l fun i x => f i) a = (fun l => finChoiceAux l fun i x => f i) b

Next tactic:
simp only [Multiset.quot_mk_to_coe, this]
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      simp? [Quotient.out_eq] at this says simp only [out_eq] at this
      simp only [Multiset.quot_mk_to_coe, this]
      

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : List ι
h : a ≈ b
this : ∀ (a : List ι), (finChoiceAux a fun i h => f i) = ⟦fun i x => out (f i)⟧
⊢ (_ : ⟦a⟧ = ⟦b⟧) ▸ ⟦fun i x => out (f i)⟧ = ⟦fun i x => out (f i)⟧

Next tactic:
let g := fun a : Multiset ι =>
        (⟦fun (i : ι) (_ : i ∈ a) => Quotient.out (f i)⟧ : Quotient (by infer_instance))
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      simp? [Quotient.out_eq] at this says simp only [out_eq] at this
      simp only [Multiset.quot_mk_to_coe, this]
      let g := fun a : Multiset ι =>
        (⟦fun (i : ι) (_ : i ∈ a) => Quotient.out (f i)⟧ : Quotient (by 

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a✝ b : List ι
h : a✝ ≈ b
this : ∀ (a : List ι), (finChoiceAux a fun i h => f i) = ⟦fun i x => out (f i)⟧
a : Multiset ι
⊢ Setoid ((i : ι) → i ∈ a → α i)

Next tactic:
infer_instance
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      simp? [Quotient.out_eq] at this says simp only [out_eq] at this
      simp only [Multiset.quot_mk_to_coe, this]
      let g := fun a : Multiset ι =>
        (⟦fun (i : ι) (_ : i ∈ a) => Quotient.out (f i)⟧ : Quotient (by infer_instance))
      

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : List ι
h : a ≈ b
this : ∀ (a : List ι), (finChoiceAux a fun i h => f i) = ⟦fun i x => out (f i)⟧
g : (a : Multiset ι) → Quotient inferInstance := fun a => ⟦fun i x => out (f i)⟧
⊢ (_ : ⟦a⟧ = ⟦b⟧) ▸ ⟦fun i x => out (f i)⟧ = ⟦fun i x => out (f i)⟧

Next tactic:
apply eq_of_heq
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      simp? [Quotient.out_eq] at this says simp only [out_eq] at this
      simp only [Multiset.quot_mk_to_coe, this]
      let g := fun a : Multiset ι =>
        (⟦fun (i : ι) (_ : i ∈ a) => Quotient.out (f i)⟧ : Quotient (by infer_instance))
      apply eq_of_heq
      

Proof state:
case h
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : List ι
h : a ≈ b
this : ∀ (a : List ι), (finChoiceAux a fun i h => f i) = ⟦fun i x => out (f i)⟧
g : (a : Multiset ι) → Quotient inferInstance := fun a => ⟦fun i x => out (f i)⟧
⊢ HEq ((_ : ⟦a⟧ = ⟦b⟧) ▸ ⟦fun i x => out (f i)⟧) ⟦fun i x => out (f i)⟧

Next tactic:
trans (g a)
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      simp? [Quotient.out_eq] at this says simp only [out_eq] at this
      simp only [Multiset.quot_mk_to_coe, this]
      let g := fun a : Multiset ι =>
        (⟦fun (i : ι) (_ : i ∈ a) => Quotient.out (f i)⟧ : Quotient (by infer_instance))
      apply eq_of_heq
      trans (g a)
      · 

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : List ι
h : a ≈ b
this : ∀ (a : List ι), (finChoiceAux a fun i h => f i) = ⟦fun i x => out (f i)⟧
g : (a : Multiset ι) → Quotient inferInstance := fun a => ⟦fun i x => out (f i)⟧
⊢ HEq ((_ : ⟦a⟧ = ⟦b⟧) ▸ ⟦fun i x => out (f i)⟧) (g ↑a)

Next tactic:
exact eq_rec_heq (φ := fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
          (Quotient.sound h) (g a)
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      simp? [Quotient.out_eq] at this says simp only [out_eq] at this
      simp only [Multiset.quot_mk_to_coe, this]
      let g := fun a : Multiset ι =>
        (⟦fun (i : ι) (_ : i ∈ a) => Quotient.out (f i)⟧ : Quotient (by infer_instance))
      apply eq_of_heq
      trans (g a)
      · exact eq_rec_heq (φ := fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by 

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : List ι
h : a ≈ b
this : ∀ (a : List ι), (finChoiceAux a fun i h => f i) = ⟦fun i x => out (f i)⟧
g : (a : Multiset ι) → Quotient inferInstance := fun a => ⟦fun i x => out (f i)⟧
l : Multiset ι
⊢ Setoid ((i : ι) → i ∈ l → α i)

Next tactic:
infer_instance
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      simp? [Quotient.out_eq] at this says simp only [out_eq] at this
      simp only [Multiset.quot_mk_to_coe, this]
      let g := fun a : Multiset ι =>
        (⟦fun (i : ι) (_ : i ∈ a) => Quotient.out (f i)⟧ : Quotient (by infer_instance))
      apply eq_of_heq
      trans (g a)
      · exact eq_rec_heq (φ := fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
          (Quotient.sound h) (g a)
      · 

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : List ι
h : a ≈ b
this : ∀ (a : List ι), (finChoiceAux a fun i h => f i) = ⟦fun i x => out (f i)⟧
g : (a : Multiset ι) → Quotient inferInstance := fun a => ⟦fun i x => out (f i)⟧
⊢ HEq (g ↑a) ⟦fun i x => out (f i)⟧

Next tactic:
change HEq (g a) (g b)
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      simp? [Quotient.out_eq] at this says simp only [out_eq] at this
      simp only [Multiset.quot_mk_to_coe, this]
      let g := fun a : Multiset ι =>
        (⟦fun (i : ι) (_ : i ∈ a) => Quotient.out (f i)⟧ : Quotient (by infer_instance))
      apply eq_of_heq
      trans (g a)
      · exact eq_rec_heq (φ := fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
          (Quotient.sound h) (g a)
      · change HEq (g a) (g b); 

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : List ι
h : a ≈ b
this : ∀ (a : List ι), (finChoiceAux a fun i h => f i) = ⟦fun i x => out (f i)⟧
g : (a : Multiset ι) → Quotient inferInstance := fun a => ⟦fun i x => out (f i)⟧
⊢ HEq (g ↑a) (g ↑b)

Next tactic:
congr 1
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      simp? [Quotient.out_eq] at this says simp only [out_eq] at this
      simp only [Multiset.quot_mk_to_coe, this]
      let g := fun a : Multiset ι =>
        (⟦fun (i : ι) (_ : i ∈ a) => Quotient.out (f i)⟧ : Quotient (by infer_instance))
      apply eq_of_heq
      trans (g a)
      · exact eq_rec_heq (φ := fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
          (Quotient.sound h) (g a)
      · change HEq (g a) (g b); congr 1; 

Proof state:
case e_1
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : List ι
h : a ≈ b
this : ∀ (a : List ι), (finChoiceAux a fun i h => f i) = ⟦fun i x => out (f i)⟧
g : (a : Multiset ι) → Quotient inferInstance := fun a => ⟦fun i x => out (f i)⟧
⊢ ↑a = ↑b

Next tactic:
exact Quotient.sound h
/-- Given a collection of setoids indexed by a fintype `ι` and a
function that for each `i : ι` gives a term of the corresponding
quotient type, then there is corresponding term in the quotient of the
product of the setoids. -/
def Quotient.finChoice {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [S : ∀ i, Setoid (α i)] (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) :=
  Quotient.liftOn
    (@Quotient.recOn _ _ (fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
      Finset.univ.1 (fun l => Quotient.finChoiceAux l fun i _ => f i) (fun a b h => by
      have := fun a => Quotient.finChoiceAux_eq a fun i _ => Quotient.out (f i)
      simp? [Quotient.out_eq] at this says simp only [out_eq] at this
      simp only [Multiset.quot_mk_to_coe, this]
      let g := fun a : Multiset ι =>
        (⟦fun (i : ι) (_ : i ∈ a) => Quotient.out (f i)⟧ : Quotient (by infer_instance))
      apply eq_of_heq
      trans (g a)
      · exact eq_rec_heq (φ := fun l : Multiset ι => @Quotient (∀ i ∈ l, α i) (by infer_instance))
          (Quotient.sound h) (g a)
      · change HEq (g a) (g b); congr 1; exact Quotient.sound h))
    (fun f => ⟦fun i => f i (Finset.mem_univ _)⟧) (fun a b h => Quotient.sound fun i => by 

Proof state:
ι : Type u_1
inst✝¹ : DecidableEq ι
inst✝ : Fintype ι
α : ι → Type u_2
S : (i : ι) → Setoid (α i)
f : (i : ι) → Quotient (S i)
a b : (i : ι) → i ∈ Finset.univ.val → α i
h : a ≈ b
i : ι
⊢ a i (_ : i ∈ Finset.univ) ≈ b i (_ : i ∈ Finset.univ)

Next tactic:
apply h
theorem Quotient.finChoice_eq {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [∀ i, Setoid (α i)] (f : ∀ i, α i) : (Quotient.finChoice fun i => ⟦f i⟧) = ⟦f⟧ := by
  

Proof state:
ι : Type u_1
inst✝² : DecidableEq ι
inst✝¹ : Fintype ι
α : ι → Type u_2
inst✝ : (i : ι) → Setoid (α i)
f : (i : ι) → α i
⊢ (finChoice fun i => ⟦f i⟧) = ⟦f⟧

Next tactic:
dsimp only [Quotient.finChoice]
theorem Quotient.finChoice_eq {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [∀ i, Setoid (α i)] (f : ∀ i, α i) : (Quotient.finChoice fun i => ⟦f i⟧) = ⟦f⟧ := by
  dsimp only [Quotient.finChoice]
  

Proof state:
ι : Type u_1
inst✝² : DecidableEq ι
inst✝¹ : Fintype ι
α : ι → Type u_2
inst✝ : (i : ι) → Setoid (α i)
f : (i : ι) → α i
⊢ Quotient.liftOn
      (Quotient.recOn Finset.univ.val (fun l => finChoiceAux l fun i x => ⟦f i⟧)
        (_ :
          ∀ (a b : List ι) (h : a ≈ b),
            (_ : ⟦a⟧ = ⟦b⟧) ▸ (fun l => finChoiceAux l fun i x => ⟦f i⟧) a =
              (fun l => finChoiceAux l fun i x => ⟦f i⟧) b))
      (fun f => ⟦fun i => f i (_ : i ∈ Finset.univ)⟧)
      (_ :
        ∀ (a b : (i : ι) → i ∈ Finset.univ.val → α i),
          a ≈ b → ⟦fun i => a i (_ : i ∈ Finset.univ)⟧ = ⟦fun i => b i (_ : i ∈ Finset.univ)⟧) =
    ⟦f⟧

Next tactic:
conv_lhs =>
    enter [1]
    tactic =>
      change _ = ⟦fun i _ => f i⟧
      exact Quotient.inductionOn (@Finset.univ ι _).1 fun l => Quotient.finChoiceAux_eq _ _
theorem Quotient.finChoice_eq {ι : Type*} [DecidableEq ι] [Fintype ι] {α : ι → Type*}
    [∀ i, Setoid (α i)] (f : ∀ i, α i) : (Quotient.finChoice fun i => ⟦f i⟧) = ⟦f⟧ := by
  dsimp only [Quotient.finChoice]
  conv_lhs =>
    

Proof state:
ι : Type u_1
inst✝² : DecidableEq ι
inst✝¹ : Fintype ι
α : ι → Type u_2
inst✝ : (i : ι) → Setoid (α i)
f : (i : ι) → α i
| Quotient.liftOn
    (Quotient.recOn Finset.univ.val (fun l => finChoiceAux l fun i x => ⟦f i⟧)
      (_ :
        ∀ (a b : List ι) (h : a ≈ b),
          (_ : ⟦a⟧ = ⟦b⟧) ▸ (fun l => finChoiceAux l fun i x => ⟦f i⟧) a =
            (fun l => finChoiceAux l fun i x => ⟦f i⟧) b))
    (fun f => ⟦fun i => f i (_ : i ∈ Finset.univ)⟧)
    (_ :
      ∀ (a b : (i : ι) → i ∈ Finset.univ.val → α i),
        a ≈ b → ⟦fun i => a i (_ : i ∈ Finset.univ)⟧ = ⟦fun i => b i (_ : i ∈ Finset.univ)⟧)

Next tactic:
enter [1]
    tactic =>
      change _ = ⟦fun i _ => f i⟧
      exact Quotient.inductionOn (@Finset.univ ι _).1 fun l => Quotient.finChoiceAux_eq _ _