l3lab/ntp-mathlib huggingface dataset:
instance isNoetherian_pi {R ι : Type*} {M : ι → Type*}
    [Ring R] [∀ i, AddCommGroup (M i)] [∀ i, Module R (M i)] [Finite ι]
    [∀ i, IsNoetherian R (M i)] : IsNoetherian R (∀ i, M i) := by
  cases nonempty_fintype ι
  haveI := Classical.decEq ι
  suffices on_finset : ∀ s : Finset ι, IsNoetherian R (∀ i : s, M i)
  · let coe_e := Equiv.subtypeUnivEquiv <| @Finset.mem_univ ι _
    letI : IsNoetherian R (∀ i : Finset.univ, M (coe_e i)) := on_finset Finset.univ
    exact isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R M coe_e)
  intro s
  induction' s using Finset.induction with a s has ih
  · exact ⟨fun s => by
      have : s = ⊥ := by simp only [eq_iff_true_of_subsingleton]
      rw [this]
      apply Submodule.fg_bot⟩
  

Proof state:
case on_finset.insert
R✝ : Type u_1
M✝ : Type u_2
P : Type u_3
inst✝⁹ : Ring R✝
inst✝⁸ : AddCommGroup M✝
inst✝⁷ : AddCommGroup P
inst✝⁶ : Module R✝ M✝
inst✝⁵ : Module R✝ P
R : Type u_4
ι : Type u_5
M : ι → Type u_6
inst✝⁴ : Ring R
inst✝³ : (i : ι) → AddCommGroup (M i)
inst✝² : (i : ι) → Module R (M i)
inst✝¹ : Finite ι
inst✝ : ∀ (i : ι), IsNoetherian R (M i)
val✝ : Fintype ι
this : DecidableEq ι
a : ι
s : Finset ι
has : a ∉ s
ih : IsNoetherian R ((i : { x // x ∈ s }) → M ↑i)
⊢ IsNoetherian R ((i : { x // x ∈ insert a s }) → M ↑i)

Next tactic:
refine
    @isNoetherian_of_linearEquiv R (M a × ((i : s) → M i)) _ _ _ _ _ _ ?_ <|
      @isNoetherian_prod R (M a) _ _ _ _ _ _ _ ih
instance isNoetherian_pi {R ι : Type*} {M : ι → Type*}
    [Ring R] [∀ i, AddCommGroup (M i)] [∀ i, Module R (M i)] [Finite ι]
    [∀ i, IsNoetherian R (M i)] : IsNoetherian R (∀ i, M i) := by
  cases nonempty_fintype ι
  haveI := Classical.decEq ι
  suffices on_finset : ∀ s : Finset ι, IsNoetherian R (∀ i : s, M i)
  · let coe_e := Equiv.subtypeUnivEquiv <| @Finset.mem_univ ι _
    letI : IsNoetherian R (∀ i : Finset.univ, M (coe_e i)) := on_finset Finset.univ
    exact isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R M coe_e)
  intro s
  induction' s using Finset.induction with a s has ih
  · exact ⟨fun s => by
      have : s = ⊥ := by simp only [eq_iff_true_of_subsingleton]
      rw [this]
      apply Submodule.fg_bot⟩
  refine
    @isNoetherian_of_linearEquiv R (M a × ((i : s) → M i)) _ _ _ _ _ _ ?_ <|
      @isNoetherian_prod R (M a) _ _ _ _ _ _ _ ih
  

Proof state:
case on_finset.insert
R✝ : Type u_1
M✝ : Type u_2
P : Type u_3
inst✝⁹ : Ring R✝
inst✝⁸ : AddCommGroup M✝
inst✝⁷ : AddCommGroup P
inst✝⁶ : Module R✝ M✝
inst✝⁵ : Module R✝ P
R : Type u_4
ι : Type u_5
M : ι → Type u_6
inst✝⁴ : Ring R
inst✝³ : (i : ι) → AddCommGroup (M i)
inst✝² : (i : ι) → Module R (M i)
inst✝¹ : Finite ι
inst✝ : ∀ (i : ι), IsNoetherian R (M i)
val✝ : Fintype ι
this : DecidableEq ι
a : ι
s : Finset ι
has : a ∉ s
ih : IsNoetherian R ((i : { x // x ∈ s }) → M ↑i)
⊢ (M a × ((i : { x // x ∈ s }) → M ↑i)) ≃ₗ[R] (i : { x // x ∈ insert a s }) → M ↑i

Next tactic:
refine
  { toFun := fun f i =>
      (Finset.mem_insert.1 i.2).by_cases
        (fun h : i.1 = a => show M i.1 from Eq.recOn h.symm f.1)
        (fun h : i.1 ∈ s => show M i.1 from f.2 ⟨i.1, h⟩),
    invFun := fun f =>
      (f ⟨a, Finset.mem_insert_self _ _⟩, fun i => f ⟨i.1, Finset.mem_insert_of_mem i.2⟩),
    map_add' := ?_,
    map_smul' := ?_
    left_inv := ?_,
    right_inv := ?_ }
instance isNoetherian_pi {R ι : Type*} {M : ι → Type*}
    [Ring R] [∀ i, AddCommGroup (M i)] [∀ i, Module R (M i)] [Finite ι]
    [∀ i, IsNoetherian R (M i)] : IsNoetherian R (∀ i, M i) := by
  cases nonempty_fintype ι
  haveI := Classical.decEq ι
  suffices on_finset : ∀ s : Finset ι, IsNoetherian R (∀ i : s, M i)
  · let coe_e := Equiv.subtypeUnivEquiv <| @Finset.mem_univ ι _
    letI : IsNoetherian R (∀ i : Finset.univ, M (coe_e i)) := on_finset Finset.univ
    exact isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R M coe_e)
  intro s
  induction' s using Finset.induction with a s has ih
  · exact ⟨fun s => by
      have : s = ⊥ := by simp only [eq_iff_true_of_subsingleton]
      rw [this]
      apply Submodule.fg_bot⟩
  refine
    @isNoetherian_of_linearEquiv R (M a × ((i : s) → M i)) _ _ _ _ _ _ ?_ <|
      @isNoetherian_prod R (M a) _ _ _ _ _ _ _ ih
  refine
  { toFun := fun f i =>
      (Finset.mem_insert.1 i.2).by_cases
        (fun h : i.1 = a => show M i.1 from Eq.recOn h.symm f.1)
        (fun h : i.1 ∈ s => show M i.1 from f.2 ⟨i.1, h⟩),
    invFun := fun f =>
      (f ⟨a, Finset.mem_insert_self _ _⟩, fun i => f ⟨i.1, Finset.mem_insert_of_mem i.2⟩),
    map_add' := ?_,
    map_smul' := ?_
    left_inv := ?_,
    right_inv := ?_ }
  · 

Proof state:
case on_finset.insert.refine_1
R✝ : Type u_1
M✝ : Type u_2
P : Type u_3
inst✝⁹ : Ring R✝
inst✝⁸ : AddCommGroup M✝
inst✝⁷ : AddCommGroup P
inst✝⁶ : Module R✝ M✝
inst✝⁵ : Module R✝ P
R : Type u_4
ι : Type u_5
M : ι → Type u_6
inst✝⁴ : Ring R
inst✝³ : (i : ι) → AddCommGroup (M i)
inst✝² : (i : ι) → Module R (M i)
inst✝¹ : Finite ι
inst✝ : ∀ (i : ι), IsNoetherian R (M i)
val✝ : Fintype ι
this : DecidableEq ι
a : ι
s : Finset ι
has : a ∉ s
ih : IsNoetherian R ((i : { x // x ∈ s }) → M ↑i)
⊢ ∀ (x y : M a × ((i : { x // x ∈ s }) → M ↑i)),
    (fun f i =>
          Or.by_cases (_ : ↑i = a ∨ ↑i ∈ s)
            (fun h =>
              let_fun this := Eq.recOn (_ : a = ↑i) f.1;
              this)
            fun h =>
            let_fun this := f.2 { val := ↑i, property := h };
            this)
        (x + y) =
      (fun f i =>
            Or.by_cases (_ : ↑i = a ∨ ↑i ∈ s)
              (fun h =>
                let_fun this := Eq.recOn (_ : a = ↑i) f.1;
                this)
              fun h =>
              let_fun this := f.2 { val := ↑i, property := h };
              this)
          x +
        (fun f i =>
            Or.by_cases (_ : ↑i = a ∨ ↑i ∈ s)
              (fun h =>
                let_fun this := Eq.recOn (_ : a = ↑i) f.1;
                this)
              fun h =>
              let_fun this := f.2 { val := ↑i, property := h };
              this)
          y

Next tactic:
intro f g
instance isNoetherian_pi {R ι : Type*} {M : ι → Type*}
    [Ring R] [∀ i, AddCommGroup (M i)] [∀ i, Module R (M i)] [Finite ι]
    [∀ i, IsNoetherian R (M i)] : IsNoetherian R (∀ i, M i) := by
  cases nonempty_fintype ι
  haveI := Classical.decEq ι
  suffices on_finset : ∀ s : Finset ι, IsNoetherian R (∀ i : s, M i)
  · let coe_e := Equiv.subtypeUnivEquiv <| @Finset.mem_univ ι _
    letI : IsNoetherian R (∀ i : Finset.univ, M (coe_e i)) := on_finset Finset.univ
    exact isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R M coe_e)
  intro s
  induction' s using Finset.induction with a s has ih
  · exact ⟨fun s => by
      have : s = ⊥ := by simp only [eq_iff_true_of_subsingleton]
      rw [this]
      apply Submodule.fg_bot⟩
  refine
    @isNoetherian_of_linearEquiv R (M a × ((i : s) → M i)) _ _ _ _ _ _ ?_ <|
      @isNoetherian_prod R (M a) _ _ _ _ _ _ _ ih
  refine
  { toFun := fun f i =>
      (Finset.mem_insert.1 i.2).by_cases
        (fun h : i.1 = a => show M i.1 from Eq.recOn h.symm f.1)
        (fun h : i.1 ∈ s => show M i.1 from f.2 ⟨i.1, h⟩),
    invFun := fun f =>
      (f ⟨a, Finset.mem_insert_self _ _⟩, fun i => f ⟨i.1, Finset.mem_insert_of_mem i.2⟩),
    map_add' := ?_,
    map_smul' := ?_
    left_inv := ?_,
    right_inv := ?_ }
  · intro f g
    

Proof state:
case on_finset.insert.refine_1
R✝ : Type u_1
M✝ : Type u_2
P : Type u_3
inst✝⁹ : Ring R✝
inst✝⁸ : AddCommGroup M✝
inst✝⁷ : AddCommGroup P
inst✝⁶ : Module R✝ M✝
inst✝⁵ : Module R✝ P
R : Type u_4
ι : Type u_5
M : ι → Type u_6
inst✝⁴ : Ring R
inst✝³ : (i : ι) → AddCommGroup (M i)
inst✝² : (i : ι) → Module R (M i)
inst✝¹ : Finite ι
inst✝ : ∀ (i : ι), IsNoetherian R (M i)
val✝ : Fintype ι
this : DecidableEq ι
a : ι
s : Finset ι
has : a ∉ s
ih : IsNoetherian R ((i : { x // x ∈ s }) → M ↑i)
f g : M a × ((i : { x // x ∈ s }) → M ↑i)
⊢ (fun f i =>
        Or.by_cases (_ : ↑i = a ∨ ↑i ∈ s)
          (fun h =>
            let_fun this := Eq.recOn (_ : a = ↑i) f.1;
            this)
          fun h =>
          let_fun this := f.2 { val := ↑i, property := h };
          this)
      (f + g) =
    (fun f i =>
          Or.by_cases (_ : ↑i = a ∨ ↑i ∈ s)
            (fun h =>
              let_fun this := Eq.recOn (_ : a = ↑i) f.1;
              this)
            fun h =>
            let_fun this := f.2 { val := ↑i, property := h };
            this)
        f +
      (fun f i =>
          Or.by_cases (_ : ↑i = a ∨ ↑i ∈ s)
            (fun h =>
              let_fun this := Eq.recOn (_ : a = ↑i) f.1;
              this)
            fun h =>
            let_fun this := f.2 { val := ↑i, property := h };
            this)
        g

Next tactic:
ext i
instance isNoetherian_pi {R ι : Type*} {M : ι → Type*}
    [Ring R] [∀ i, AddCommGroup (M i)] [∀ i, Module R (M i)] [Finite ι]
    [∀ i, IsNoetherian R (M i)] : IsNoetherian R (∀ i, M i) := by
  cases nonempty_fintype ι
  haveI := Classical.decEq ι
  suffices on_finset : ∀ s : Finset ι, IsNoetherian R (∀ i : s, M i)
  · let coe_e := Equiv.subtypeUnivEquiv <| @Finset.mem_univ ι _
    letI : IsNoetherian R (∀ i : Finset.univ, M (coe_e i)) := on_finset Finset.univ
    exact isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R M coe_e)
  intro s
  induction' s using Finset.induction with a s has ih
  · exact ⟨fun s => by
      have : s = ⊥ := by simp only [eq_iff_true_of_subsingleton]
      rw [this]
      apply Submodule.fg_bot⟩
  refine
    @isNoetherian_of_linearEquiv R (M a × ((i : s) → M i)) _ _ _ _ _ _ ?_ <|
      @isNoetherian_prod R (M a) _ _ _ _ _ _ _ ih
  refine
  { toFun := fun f i =>
      (Finset.mem_insert.1 i.2).by_cases
        (fun h : i.1 = a => show M i.1 from Eq.recOn h.symm f.1)
        (fun h : i.1 ∈ s => show M i.1 from f.2 ⟨i.1, h⟩),
    invFun := fun f =>
      (f ⟨a, Finset.mem_insert_self _ _⟩, fun i => f ⟨i.1, Finset.mem_insert_of_mem i.2⟩),
    map_add' := ?_,
    map_smul' := ?_
    left_inv := ?_,
    right_inv := ?_ }
  · intro f g
    ext i
    

Proof state:
case on_finset.insert.refine_1.h
R✝ : Type u_1
M✝ : Type u_2
P : Type u_3
inst✝⁹ : Ring R✝
inst✝⁸ : AddCommGroup M✝
inst✝⁷ : AddCommGroup P
inst✝⁶ : Module R✝ M✝
inst✝⁵ : Module R✝ P
R : Type u_4
ι : Type u_5
M : ι → Type u_6
inst✝⁴ : Ring R
inst✝³ : (i : ι) → AddCommGroup (M i)
inst✝² : (i : ι) → Module R (M i)
inst✝¹ : Finite ι
inst✝ : ∀ (i : ι), IsNoetherian R (M i)
val✝ : Fintype ι
this : DecidableEq ι
a : ι
s : Finset ι
has : a ∉ s
ih : IsNoetherian R ((i : { x // x ∈ s }) → M ↑i)
f g : M a × ((i : { x // x ∈ s }) → M ↑i)
i : { x // x ∈ insert a s }
⊢ (fun f i =>
        Or.by_cases (_ : ↑i = a ∨ ↑i ∈ s)
          (fun h =>
            let_fun this := Eq.recOn (_ : a = ↑i) f.1;
            this)
          fun h =>
          let_fun this := f.2 { val := ↑i, property := h };
          this)
      (f + g) i =
    ((fun f i =>
            Or.by_cases (_ : ↑i = a ∨ ↑i ∈ s)
              (fun h =>
                let_fun this := Eq.recOn (_ : a = ↑i) f.1;
                this)
              fun h =>
              let_fun this := f.2 { val := ↑i, property := h };
              this)
          f +
        (fun f i =>
            Or.by_cases (_ : ↑i = a ∨ ↑i ∈ s)
              (fun h =>
                let_fun this := Eq.recOn (_ : a = ↑i) f.1;
                this)
              fun h =>
              let_fun this := f.2 { val := ↑i, property := h };
              this)
          g)
      i

Next tactic:
unfold Or.by_cases
instance isNoetherian_pi {R ι : Type*} {M : ι → Type*}
    [Ring R] [∀ i, AddCommGroup (M i)] [∀ i, Module R (M i)] [Finite ι]
    [∀ i, IsNoetherian R (M i)] : IsNoetherian R (∀ i, M i) := by
  cases nonempty_fintype ι
  haveI := Classical.decEq ι
  suffices on_finset : ∀ s : Finset ι, IsNoetherian R (∀ i : s, M i)
  · let coe_e := Equiv.subtypeUnivEquiv <| @Finset.mem_univ ι _
    letI : IsNoetherian R (∀ i : Finset.univ, M (coe_e i)) := on_finset Finset.univ
    exact isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R M coe_e)
  intro s
  induction' s using Finset.induction with a s has ih
  · exact ⟨fun s => by
      have : s = ⊥ := by simp only [eq_iff_true_of_subsingleton]
      rw [this]
      apply Submodule.fg_bot⟩
  refine
    @isNoetherian_of_linearEquiv R (M a × ((i : s) → M i)) _ _ _ _ _ _ ?_ <|
      @isNoetherian_prod R (M a) _ _ _ _ _ _ _ ih
  refine
  { toFun := fun f i =>
      (Finset.mem_insert.1 i.2).by_cases
        (fun h : i.1 = a => show M i.1 from Eq.recOn h.symm f.1)
        (fun h : i.1 ∈ s => show M i.1 from f.2 ⟨i.1, h⟩),
    invFun := fun f =>
      (f ⟨a, Finset.mem_insert_self _ _⟩, fun i => f ⟨i.1, Finset.mem_insert_of_mem i.2⟩),
    map_add' := ?_,
    map_smul' := ?_
    left_inv := ?_,
    right_inv := ?_ }
  · intro f g
    ext i
    unfold Or.by_cases
    

Proof state:
case on_finset.insert.refine_1.h
R✝ : Type u_1
M✝ : Type u_2
P : Type u_3
inst✝⁹ : Ring R✝
inst✝⁸ : AddCommGroup M✝
inst✝⁷ : AddCommGroup P
inst✝⁶ : Module R✝ M✝
inst✝⁵ : Module R✝ P
R : Type u_4
ι : Type u_5
M : ι → Type u_6
inst✝⁴ : Ring R
inst✝³ : (i : ι) → AddCommGroup (M i)
inst✝² : (i : ι) → Module R (M i)
inst✝¹ : Finite ι
inst✝ : ∀ (i : ι), IsNoetherian R (M i)
val✝ : Fintype ι
this : DecidableEq ι
a : ι
s : Finset ι
has : a ∉ s
ih : IsNoetherian R ((i : { x // x ∈ s }) → M ↑i)
f g : M a × ((i : { x // x ∈ s }) → M ↑i)
i : { x // x ∈ insert a s }
⊢ (fun f i =>
        if hp : ↑i = a then
          (fun h =>
              let_fun this := Eq.recOn (_ : a = ↑i) f.1;
              this)
            hp
        else
          (fun h =>
              let_fun this := f.2 { val := ↑i, property := h };
              this)
            (_ : ↑i ∈ s))
      (f + g) i =
    ((fun f i =>
            if hp : ↑i = a then
              (fun h =>
                  let_fun this := Eq.recOn (_ : a = ↑i) f.1;
                  this)
                hp
            else
              (fun h =>
                  let_fun this := f.2 { val := ↑i, property := h };
                  this)
                (_ : ↑i ∈ s))
          f +
        (fun f i =>
            if hp : ↑i = a then
              (fun h =>
                  let_fun this := Eq.recOn (_ : a = ↑i) f.1;
                  this)
                hp
            else
              (fun h =>
                  let_fun this := f.2 { val := ↑i, property := h };
                  this)
                (_ : ↑i ∈ s))
          g)
      i

Next tactic:
cases' i with i hi
instance isNoetherian_pi {R ι : Type*} {M : ι → Type*}
    [Ring R] [∀ i, AddCommGroup (M i)] [∀ i, Module R (M i)] [Finite ι]
    [∀ i, IsNoetherian R (M i)] : IsNoetherian R (∀ i, M i) := by
  cases nonempty_fintype ι
  haveI := Classical.decEq ι
  suffices on_finset : ∀ s : Finset ι, IsNoetherian R (∀ i : s, M i)
  · let coe_e := Equiv.subtypeUnivEquiv <| @Finset.mem_univ ι _
    letI : IsNoetherian R (∀ i : Finset.univ, M (coe_e i)) := on_finset Finset.univ
    exact isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R M coe_e)
  intro s
  induction' s using Finset.induction with a s has ih
  · exact ⟨fun s => by
      have : s = ⊥ := by simp only [eq_iff_true_of_subsingleton]
      rw [this]
      apply Submodule.fg_bot⟩
  refine
    @isNoetherian_of_linearEquiv R (M a × ((i : s) → M i)) _ _ _ _ _ _ ?_ <|
      @isNoetherian_prod R (M a) _ _ _ _ _ _ _ ih
  refine
  { toFun := fun f i =>
      (Finset.mem_insert.1 i.2).by_cases
        (fun h : i.1 = a => show M i.1 from Eq.recOn h.symm f.1)
        (fun h : i.1 ∈ s => show M i.1 from f.2 ⟨i.1, h⟩),
    invFun := fun f =>
      (f ⟨a, Finset.mem_insert_self _ _⟩, fun i => f ⟨i.1, Finset.mem_insert_of_mem i.2⟩),
    map_add' := ?_,
    map_smul' := ?_
    left_inv := ?_,
    right_inv := ?_ }
  · intro f g
    ext i
    unfold Or.by_cases
    cases' i with i hi
    

Proof state:
case on_finset.insert.refine_1.h.mk
R✝ : Type u_1
M✝ : Type u_2
P : Type u_3
inst✝⁹ : Ring R✝
inst✝⁸ : AddCommGroup M✝
inst✝⁷ : AddCommGroup P
inst✝⁶ : Module R✝ M✝
inst✝⁵ : Module R✝ P
R : Type u_4
ι : Type u_5
M : ι → Type u_6
inst✝⁴ : Ring R
inst✝³ : (i : ι) → AddCommGroup (M i)
inst✝² : (i : ι) → Module R (M i)
inst✝¹ : Finite ι
inst✝ : ∀ (i : ι), IsNoetherian R (M i)
val✝ : Fintype ι
this : DecidableEq ι
a : ι
s : Finset ι
has : a ∉ s
ih : IsNoetherian R ((i : { x // x ∈ s }) → M ↑i)
f g : M a × ((i : { x // x ∈ s }) → M ↑i)
i : ι
hi : i ∈ insert a s
⊢ (fun f i =>
        if hp : ↑i = a then
          (fun h =>
              let_fun this := Eq.recOn (_ : a = ↑i) f.1;
              this)
            hp
        else
          (fun h =>
              let_fun this := f.2 { val := ↑i, property := h };
              this)
            (_ : ↑i ∈ s))
      (f + g) { val := i, property := hi } =
    ((fun f i =>
            if hp : ↑i = a then
              (fun h =>
                  let_fun this := Eq.recOn (_ : a = ↑i) f.1;
                  this)
                hp
            else
              (fun h =>
                  let_fun this := f.2 { val := ↑i, property := h };
                  this)
                (_ : ↑i ∈ s))
          f +
        (fun f i =>
            if hp : ↑i = a then
              (fun h =>
                  let_fun this := Eq.recOn (_ : a = ↑i) f.1;
                  this)
                hp
            else
              (fun h =>
                  let_fun this := f.2 { val := ↑i, property := h };
                  this)
                (_ : ↑i ∈ s))
          g)
      { val := i, property := hi }

Next tactic:
rcases Finset.mem_insert.1 hi with (rfl | h)
instance isNoetherian_pi {R ι : Type*} {M : ι → Type*}
    [Ring R] [∀ i, AddCommGroup (M i)] [∀ i, Module R (M i)] [Finite ι]
    [∀ i, IsNoetherian R (M i)] : IsNoetherian R (∀ i, M i) := by
  cases nonempty_fintype ι
  haveI := Classical.decEq ι
  suffices on_finset : ∀ s : Finset ι, IsNoetherian R (∀ i : s, M i)
  · let coe_e := Equiv.subtypeUnivEquiv <| @Finset.mem_univ ι _
    letI : IsNoetherian R (∀ i : Finset.univ, M (coe_e i)) := on_finset Finset.univ
    exact isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R M coe_e)
  intro s
  induction' s using Finset.induction with a s has ih
  · exact ⟨fun s => by
      have : s = ⊥ := by simp only [eq_iff_true_of_subsingleton]
      rw [this]
      apply Submodule.fg_bot⟩
  refine
    @isNoetherian_of_linearEquiv R (M a × ((i : s) → M i)) _ _ _ _ _ _ ?_ <|
      @isNoetherian_prod R (M a) _ _ _ _ _ _ _ ih
  refine
  { toFun := fun f i =>
      (Finset.mem_insert.1 i.2).by_cases
        (fun h : i.1 = a => show M i.1 from Eq.recOn h.symm f.1)
        (fun h : i.1 ∈ s => show M i.1 from f.2 ⟨i.1, h⟩),
    invFun := fun f =>
      (f ⟨a, Finset.mem_insert_self _ _⟩, fun i => f ⟨i.1, Finset.mem_insert_of_mem i.2⟩),
    map_add' := ?_,
    map_smul' := ?_
    left_inv := ?_,
    right_inv := ?_ }
  · intro f g
    ext i
    unfold Or.by_cases
    cases' i with i hi
    rcases Finset.mem_insert.1 hi with (rfl | h)
    · 

Proof state:
case on_finset.insert.refine_1.h.mk.inl
R✝ : Type u_1
M✝ : Type u_2
P : Type u_3
inst✝⁹ : Ring R✝
inst✝⁸ : AddCommGroup M✝
inst✝⁷ : AddCommGroup P
inst✝⁶ : Module R✝ M✝
inst✝⁵ : Module R✝ P
R : Type u_4
ι : Type u_5
M : ι → Type u_6
inst✝⁴ : Ring R
inst✝³ : (i : ι) → AddCommGroup (M i)
inst✝² : (i : ι) → Module R (M i)
inst✝¹ : Finite ι
inst✝ : ∀ (i : ι), IsNoetherian R (M i)
val✝ : Fintype ι
this : DecidableEq ι
s : Finset ι
ih : IsNoetherian R ((i : { x // x ∈ s }) → M ↑i)
i : ι
has : i ∉ s
f g : M i × ((i : { x // x ∈ s }) → M ↑i)
hi : i ∈ insert i s
⊢ (fun f i_1 =>
        if hp : ↑i_1 = i then
          (fun h =>
              let_fun this := Eq.recOn (_ : i = ↑i_1) f.1;
              this)
            hp
        else
          (fun h =>
              let_fun this := f.2 { val := ↑i_1, property := h };
              this)
            (_ : ↑i_1 ∈ s))
      (f + g) { val := i, property := hi } =
    ((fun f i_1 =>
            if hp : ↑i_1 = i then
              (fun h =>
                  let_fun this := Eq.recOn (_ : i = ↑i_1) f.1;
                  this)
                hp
            else
              (fun h =>
                  let_fun this := f.2 { val := ↑i_1, property := h };
                  this)
                (_ : ↑i_1 ∈ s))
          f +
        (fun f i_1 =>
            if hp : ↑i_1 = i then
              (fun h =>
                  let_fun this := Eq.recOn (_ : i = ↑i_1) f.1;
                  this)
                hp
            else
              (fun h =>
                  let_fun this := f.2 { val := ↑i_1, property := h };
                  this)
                (_ : ↑i_1 ∈ s))
          g)
      { val := i, property := hi }

Next tactic:
change _ = _ + _
instance isNoetherian_pi {R ι : Type*} {M : ι → Type*}
    [Ring R] [∀ i, AddCommGroup (M i)] [∀ i, Module R (M i)] [Finite ι]
    [∀ i, IsNoetherian R (M i)] : IsNoetherian R (∀ i, M i) := by
  cases nonempty_fintype ι
  haveI := Classical.decEq ι
  suffices on_finset : ∀ s : Finset ι, IsNoetherian R (∀ i : s, M i)
  · let coe_e := Equiv.subtypeUnivEquiv <| @Finset.mem_univ ι _
    letI : IsNoetherian R (∀ i : Finset.univ, M (coe_e i)) := on_finset Finset.univ
    exact isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R M coe_e)
  intro s
  induction' s using Finset.induction with a s has ih
  · exact ⟨fun s => by
      have : s = ⊥ := by simp only [eq_iff_true_of_subsingleton]
      rw [this]
      apply Submodule.fg_bot⟩
  refine
    @isNoetherian_of_linearEquiv R (M a × ((i : s) → M i)) _ _ _ _ _ _ ?_ <|
      @isNoetherian_prod R (M a) _ _ _ _ _ _ _ ih
  refine
  { toFun := fun f i =>
      (Finset.mem_insert.1 i.2).by_cases
        (fun h : i.1 = a => show M i.1 from Eq.recOn h.symm f.1)
        (fun h : i.1 ∈ s => show M i.1 from f.2 ⟨i.1, h⟩),
    invFun := fun f =>
      (f ⟨a, Finset.mem_insert_self _ _⟩, fun i => f ⟨i.1, Finset.mem_insert_of_mem i.2⟩),
    map_add' := ?_,
    map_smul' := ?_
    left_inv := ?_,
    right_inv := ?_ }
  · intro f g
    ext i
    unfold Or.by_cases
    cases' i with i hi
    rcases Finset.mem_insert.1 hi with (rfl | h)
    · change _ = _ + _
      

Proof state:
case on_finset.insert.refine_1.h.mk.inl
R✝ : Type u_1
M✝ : Type u_2
P : Type u_3
inst✝⁹ : Ring R✝
inst✝⁸ : AddCommGroup M✝
inst✝⁷ : AddCommGroup P
inst✝⁶ : Module R✝ M✝
inst✝⁵ : Module R✝ P
R : Type u_4
ι : Type u_5
M : ι → Type u_6
inst✝⁴ : Ring R
inst✝³ : (i : ι) → AddCommGroup (M i)
inst✝² : (i : ι) → Module R (M i)
inst✝¹ : Finite ι
inst✝ : ∀ (i : ι), IsNoetherian R (M i)
val✝ : Fintype ι
this : DecidableEq ι
s : Finset ι
ih : IsNoetherian R ((i : { x // x ∈ s }) → M ↑i)
i : ι
has : i ∉ s
f g : M i × ((i : { x // x ∈ s }) → M ↑i)
hi : i ∈ insert i s
⊢ (fun f i_1 =>
        if hp : ↑i_1 = i then
          (fun h =>
              let_fun this := Eq.recOn (_ : i = ↑i_1) f.1;
              this)
            hp
        else
          (fun h =>
              let_fun this := f.2 { val := ↑i_1, property := h };
              this)
            (_ : ↑i_1 ∈ s))
      (f + g) { val := i, property := hi } =
    (fun f i_1 =>
          if hp : ↑i_1 = i then
            (fun h =>
                let_fun this := Eq.recOn (_ : i = ↑i_1) f.1;
                this)
              hp
          else
            (fun h =>
                let_fun this := f.2 { val := ↑i_1, property := h };
                this)
              (_ : ↑i_1 ∈ s))
        f { val := i, property := hi } +
      (fun f i_1 =>
          if hp : ↑i_1 = i then
            (fun h =>
                let_fun this := Eq.recOn (_ : i = ↑i_1) f.1;
                this)
              hp
          else
            (fun h =>
                let_fun this := f.2 { val := ↑i_1, property := h };
                this)
              (_ : ↑i_1 ∈ s))
        g { val := i, property := hi }

Next tactic:
simp only [dif_pos]