l3lab/ntp-mathlib huggingface dataset:
theorem isSupported_of {p} {s : Set α} : IsSupported (of p) s ↔ p ∈ s :=
  suffices IsSupported (of p) s → p ∈ s from ⟨this, fun hps => Subring.subset_closure ⟨p, hps, rfl⟩⟩
  fun hps : IsSupported (of p) s => by
  haveI := Classical.decPred s
  have : ∀ x, IsSupported x s →
        ∃ n : ℤ, lift (fun a => if a ∈ s then (0 : ℤ[X]) else Polynomial.X) x = n := by
    intro x hx
    refine' Subring.InClosure.recOn hx _ _ _ _
    · use 1
      rw [RingHom.map_one]
      norm_cast
    · use -1
      rw [RingHom.map_neg, RingHom.map_one, Int.cast_neg, Int.cast_one]
    · rintro _ ⟨z, hzs, rfl⟩ _ _
      use 0
      rw [RingHom.map_mul, lift_of, if_pos hzs, zero_mul]
      norm_cast
    · rintro x y ⟨q, hq⟩ ⟨r, hr⟩
      refine' ⟨q + r, _⟩
      rw [RingHom.map_add, hq, hr]
      norm_cast
  specialize this (of p) hps
  rw [lift_of] at this
  split_ifs at this with h
  · exact h
  exfalso
  apply Ne.symm Int.zero_ne_one
  

Proof state:
case neg.h
α : Type u
β : Type v
f : α → β
p : α
s : Set α
hps : IsSupported (of p) s
this✝ : DecidablePred s
h : p ∉ s
this : ∃ n, X = ↑n
⊢ 1 = 0

Next tactic:
rcases this with ⟨w, H⟩
theorem isSupported_of {p} {s : Set α} : IsSupported (of p) s ↔ p ∈ s :=
  suffices IsSupported (of p) s → p ∈ s from ⟨this, fun hps => Subring.subset_closure ⟨p, hps, rfl⟩⟩
  fun hps : IsSupported (of p) s => by
  haveI := Classical.decPred s
  have : ∀ x, IsSupported x s →
        ∃ n : ℤ, lift (fun a => if a ∈ s then (0 : ℤ[X]) else Polynomial.X) x = n := by
    intro x hx
    refine' Subring.InClosure.recOn hx _ _ _ _
    · use 1
      rw [RingHom.map_one]
      norm_cast
    · use -1
      rw [RingHom.map_neg, RingHom.map_one, Int.cast_neg, Int.cast_one]
    · rintro _ ⟨z, hzs, rfl⟩ _ _
      use 0
      rw [RingHom.map_mul, lift_of, if_pos hzs, zero_mul]
      norm_cast
    · rintro x y ⟨q, hq⟩ ⟨r, hr⟩
      refine' ⟨q + r, _⟩
      rw [RingHom.map_add, hq, hr]
      norm_cast
  specialize this (of p) hps
  rw [lift_of] at this
  split_ifs at this with h
  · exact h
  exfalso
  apply Ne.symm Int.zero_ne_one
  rcases this with ⟨w, H⟩
  

Proof state:
case neg.h.intro
α : Type u
β : Type v
f : α → β
p : α
s : Set α
hps : IsSupported (of p) s
this : DecidablePred s
h : p ∉ s
w : ℤ
H : X = ↑w
⊢ 1 = 0

Next tactic:
rw [← Polynomial.C_eq_int_cast] at H
theorem isSupported_of {p} {s : Set α} : IsSupported (of p) s ↔ p ∈ s :=
  suffices IsSupported (of p) s → p ∈ s from ⟨this, fun hps => Subring.subset_closure ⟨p, hps, rfl⟩⟩
  fun hps : IsSupported (of p) s => by
  haveI := Classical.decPred s
  have : ∀ x, IsSupported x s →
        ∃ n : ℤ, lift (fun a => if a ∈ s then (0 : ℤ[X]) else Polynomial.X) x = n := by
    intro x hx
    refine' Subring.InClosure.recOn hx _ _ _ _
    · use 1
      rw [RingHom.map_one]
      norm_cast
    · use -1
      rw [RingHom.map_neg, RingHom.map_one, Int.cast_neg, Int.cast_one]
    · rintro _ ⟨z, hzs, rfl⟩ _ _
      use 0
      rw [RingHom.map_mul, lift_of, if_pos hzs, zero_mul]
      norm_cast
    · rintro x y ⟨q, hq⟩ ⟨r, hr⟩
      refine' ⟨q + r, _⟩
      rw [RingHom.map_add, hq, hr]
      norm_cast
  specialize this (of p) hps
  rw [lift_of] at this
  split_ifs at this with h
  · exact h
  exfalso
  apply Ne.symm Int.zero_ne_one
  rcases this with ⟨w, H⟩
  rw [← Polynomial.C_eq_int_cast] at H
  

Proof state:
case neg.h.intro
α : Type u
β : Type v
f : α → β
p : α
s : Set α
hps : IsSupported (of p) s
this : DecidablePred s
h : p ∉ s
w : ℤ
H : X = C ↑w
⊢ 1 = 0

Next tactic:
have : Polynomial.X.coeff 1 = (Polynomial.C ↑w).coeff 1 := by rw [H]; rfl
theorem isSupported_of {p} {s : Set α} : IsSupported (of p) s ↔ p ∈ s :=
  suffices IsSupported (of p) s → p ∈ s from ⟨this, fun hps => Subring.subset_closure ⟨p, hps, rfl⟩⟩
  fun hps : IsSupported (of p) s => by
  haveI := Classical.decPred s
  have : ∀ x, IsSupported x s →
        ∃ n : ℤ, lift (fun a => if a ∈ s then (0 : ℤ[X]) else Polynomial.X) x = n := by
    intro x hx
    refine' Subring.InClosure.recOn hx _ _ _ _
    · use 1
      rw [RingHom.map_one]
      norm_cast
    · use -1
      rw [RingHom.map_neg, RingHom.map_one, Int.cast_neg, Int.cast_one]
    · rintro _ ⟨z, hzs, rfl⟩ _ _
      use 0
      rw [RingHom.map_mul, lift_of, if_pos hzs, zero_mul]
      norm_cast
    · rintro x y ⟨q, hq⟩ ⟨r, hr⟩
      refine' ⟨q + r, _⟩
      rw [RingHom.map_add, hq, hr]
      norm_cast
  specialize this (of p) hps
  rw [lift_of] at this
  split_ifs at this with h
  · exact h
  exfalso
  apply Ne.symm Int.zero_ne_one
  rcases this with ⟨w, H⟩
  rw [← Polynomial.C_eq_int_cast] at H
  have : Polynomial.X.coeff 1 = (Polynomial.C ↑w).coeff 1 := by 

Proof state:
α : Type u
β : Type v
f : α → β
p : α
s : Set α
hps : IsSupported (of p) s
this : DecidablePred s
h : p ∉ s
w : ℤ
H : X = C ↑w
⊢ coeff X 1 = coeff (C w) 1

Next tactic:
rw [H]
theorem isSupported_of {p} {s : Set α} : IsSupported (of p) s ↔ p ∈ s :=
  suffices IsSupported (of p) s → p ∈ s from ⟨this, fun hps => Subring.subset_closure ⟨p, hps, rfl⟩⟩
  fun hps : IsSupported (of p) s => by
  haveI := Classical.decPred s
  have : ∀ x, IsSupported x s →
        ∃ n : ℤ, lift (fun a => if a ∈ s then (0 : ℤ[X]) else Polynomial.X) x = n := by
    intro x hx
    refine' Subring.InClosure.recOn hx _ _ _ _
    · use 1
      rw [RingHom.map_one]
      norm_cast
    · use -1
      rw [RingHom.map_neg, RingHom.map_one, Int.cast_neg, Int.cast_one]
    · rintro _ ⟨z, hzs, rfl⟩ _ _
      use 0
      rw [RingHom.map_mul, lift_of, if_pos hzs, zero_mul]
      norm_cast
    · rintro x y ⟨q, hq⟩ ⟨r, hr⟩
      refine' ⟨q + r, _⟩
      rw [RingHom.map_add, hq, hr]
      norm_cast
  specialize this (of p) hps
  rw [lift_of] at this
  split_ifs at this with h
  · exact h
  exfalso
  apply Ne.symm Int.zero_ne_one
  rcases this with ⟨w, H⟩
  rw [← Polynomial.C_eq_int_cast] at H
  have : Polynomial.X.coeff 1 = (Polynomial.C ↑w).coeff 1 := by rw [H]; 

Proof state:
α : Type u
β : Type v
f : α → β
p : α
s : Set α
hps : IsSupported (of p) s
this : DecidablePred s
h : p ∉ s
w : ℤ
H : X = C ↑w
⊢ coeff (C ↑w) 1 = coeff (C w) 1

Next tactic:
rfl
theorem isSupported_of {p} {s : Set α} : IsSupported (of p) s ↔ p ∈ s :=
  suffices IsSupported (of p) s → p ∈ s from ⟨this, fun hps => Subring.subset_closure ⟨p, hps, rfl⟩⟩
  fun hps : IsSupported (of p) s => by
  haveI := Classical.decPred s
  have : ∀ x, IsSupported x s →
        ∃ n : ℤ, lift (fun a => if a ∈ s then (0 : ℤ[X]) else Polynomial.X) x = n := by
    intro x hx
    refine' Subring.InClosure.recOn hx _ _ _ _
    · use 1
      rw [RingHom.map_one]
      norm_cast
    · use -1
      rw [RingHom.map_neg, RingHom.map_one, Int.cast_neg, Int.cast_one]
    · rintro _ ⟨z, hzs, rfl⟩ _ _
      use 0
      rw [RingHom.map_mul, lift_of, if_pos hzs, zero_mul]
      norm_cast
    · rintro x y ⟨q, hq⟩ ⟨r, hr⟩
      refine' ⟨q + r, _⟩
      rw [RingHom.map_add, hq, hr]
      norm_cast
  specialize this (of p) hps
  rw [lift_of] at this
  split_ifs at this with h
  · exact h
  exfalso
  apply Ne.symm Int.zero_ne_one
  rcases this with ⟨w, H⟩
  rw [← Polynomial.C_eq_int_cast] at H
  have : Polynomial.X.coeff 1 = (Polynomial.C ↑w).coeff 1 := by rw [H]; rfl
  

Proof state:
case neg.h.intro
α : Type u
β : Type v
f : α → β
p : α
s : Set α
hps : IsSupported (of p) s
this✝ : DecidablePred s
h : p ∉ s
w : ℤ
H : X = C ↑w
this : coeff X 1 = coeff (C w) 1
⊢ 1 = 0

Next tactic:
rwa [Polynomial.coeff_C, if_neg (one_ne_zero : 1 ≠ 0), Polynomial.coeff_X, if_pos rfl] at this
theorem map_subtype_val_restriction {x} (s : Set α) [DecidablePred (· ∈ s)]
    (hxs : IsSupported x s) : map (↑) (restriction s x) = x := by
  

Proof state:
α : Type u
β : Type v
f : α → β
x : FreeCommRing α
s : Set α
inst✝ : DecidablePred fun x => x ∈ s
hxs : IsSupported x s
⊢ (map Subtype.val) ((restriction s) x) = x

Next tactic:
refine' Subring.InClosure.recOn hxs _ _ _ _
theorem map_subtype_val_restriction {x} (s : Set α) [DecidablePred (· ∈ s)]
    (hxs : IsSupported x s) : map (↑) (restriction s x) = x := by
  refine' Subring.InClosure.recOn hxs _ _ _ _
  · 

Proof state:
case refine'_1
α : Type u
β : Type v
f : α → β
x : FreeCommRing α
s : Set α
inst✝ : DecidablePred fun x => x ∈ s
hxs : IsSupported x s
⊢ (map Subtype.val) ((restriction s) 1) = 1

Next tactic:
rw [RingHom.map_one]
theorem map_subtype_val_restriction {x} (s : Set α) [DecidablePred (· ∈ s)]
    (hxs : IsSupported x s) : map (↑) (restriction s x) = x := by
  refine' Subring.InClosure.recOn hxs _ _ _ _
  · rw [RingHom.map_one]
    

Proof state:
case refine'_1
α : Type u
β : Type v
f : α → β
x : FreeCommRing α
s : Set α
inst✝ : DecidablePred fun x => x ∈ s
hxs : IsSupported x s
⊢ (map Subtype.val) 1 = 1

Next tactic:
rfl
theorem map_subtype_val_restriction {x} (s : Set α) [DecidablePred (· ∈ s)]
    (hxs : IsSupported x s) : map (↑) (restriction s x) = x := by
  refine' Subring.InClosure.recOn hxs _ _ _ _
  · rw [RingHom.map_one]
    rfl
  · 

Proof state:
case refine'_2
α : Type u
β : Type v
f : α → β
x : FreeCommRing α
s : Set α
inst✝ : DecidablePred fun x => x ∈ s
hxs : IsSupported x s
⊢ (map Subtype.val) ((restriction s) (-1)) = -1

Next tactic:
rw [map_neg, map_one]
theorem map_subtype_val_restriction {x} (s : Set α) [DecidablePred (· ∈ s)]
    (hxs : IsSupported x s) : map (↑) (restriction s x) = x := by
  refine' Subring.InClosure.recOn hxs _ _ _ _
  · rw [RingHom.map_one]
    rfl
  · rw [map_neg, map_one]
    

Proof state:
case refine'_2
α : Type u
β : Type v
f : α → β
x : FreeCommRing α
s : Set α
inst✝ : DecidablePred fun x => x ∈ s
hxs : IsSupported x s
⊢ (map Subtype.val) (-1) = -1

Next tactic:
rfl
theorem map_subtype_val_restriction {x} (s : Set α) [DecidablePred (· ∈ s)]
    (hxs : IsSupported x s) : map (↑) (restriction s x) = x := by
  refine' Subring.InClosure.recOn hxs _ _ _ _
  · rw [RingHom.map_one]
    rfl
  · rw [map_neg, map_one]
    rfl
  · 

Proof state:
case refine'_3
α : Type u
β : Type v
f : α → β
x : FreeCommRing α
s : Set α
inst✝ : DecidablePred fun x => x ∈ s
hxs : IsSupported x s
⊢ ∀ z ∈ of '' s,
    ∀ (n : FreeCommRing α),
      (map Subtype.val) ((restriction s) n) = n → (map Subtype.val) ((restriction s) (z * n)) = z * n

Next tactic:
rintro _ ⟨p, hps, rfl⟩ n ih
theorem map_subtype_val_restriction {x} (s : Set α) [DecidablePred (· ∈ s)]
    (hxs : IsSupported x s) : map (↑) (restriction s x) = x := by
  refine' Subring.InClosure.recOn hxs _ _ _ _
  · rw [RingHom.map_one]
    rfl
  · rw [map_neg, map_one]
    rfl
  · rintro _ ⟨p, hps, rfl⟩ n ih
    

Proof state:
case refine'_3.intro.intro
α : Type u
β : Type v
f : α → β
x : FreeCommRing α
s : Set α
inst✝ : DecidablePred fun x => x ∈ s
hxs : IsSupported x s
p : α
hps : p ∈ s
n : FreeCommRing α
ih : (map Subtype.val) ((restriction s) n) = n
⊢ (map Subtype.val) ((restriction s) (of p * n)) = of p * n

Next tactic:
rw [RingHom.map_mul, restriction_of, dif_pos hps, RingHom.map_mul, map_of, ih]
theorem map_subtype_val_restriction {x} (s : Set α) [DecidablePred (· ∈ s)]
    (hxs : IsSupported x s) : map (↑) (restriction s x) = x := by
  refine' Subring.InClosure.recOn hxs _ _ _ _
  · rw [RingHom.map_one]
    rfl
  · rw [map_neg, map_one]
    rfl
  · rintro _ ⟨p, hps, rfl⟩ n ih
    rw [RingHom.map_mul, restriction_of, dif_pos hps, RingHom.map_mul, map_of, ih]
  · 

Proof state:
case refine'_4
α : Type u
β : Type v
f : α → β
x : FreeCommRing α
s : Set α
inst✝ : DecidablePred fun x => x ∈ s
hxs : IsSupported x s
⊢ ∀ {x y : FreeCommRing α},
    (map Subtype.val) ((restriction s) x) = x →
      (map Subtype.val) ((restriction s) y) = y → (map Subtype.val) ((restriction s) (x + y)) = x + y

Next tactic:
intro x y ihx ihy
theorem map_subtype_val_restriction {x} (s : Set α) [DecidablePred (· ∈ s)]
    (hxs : IsSupported x s) : map (↑) (restriction s x) = x := by
  refine' Subring.InClosure.recOn hxs _ _ _ _
  · rw [RingHom.map_one]
    rfl
  · rw [map_neg, map_one]
    rfl
  · rintro _ ⟨p, hps, rfl⟩ n ih
    rw [RingHom.map_mul, restriction_of, dif_pos hps, RingHom.map_mul, map_of, ih]
  · intro x y ihx ihy
    

Proof state:
case refine'_4
α : Type u
β : Type v
f : α → β
x✝ : FreeCommRing α
s : Set α
inst✝ : DecidablePred fun x => x ∈ s
hxs : IsSupported x✝ s
x y : FreeCommRing α
ihx : (map Subtype.val) ((restriction s) x) = x
ihy : (map Subtype.val) ((restriction s) y) = y
⊢ (map Subtype.val) ((restriction s) (x + y)) = x + y

Next tactic:
rw [RingHom.map_add, RingHom.map_add, ihx, ihy]
theorem exists_finset_support (x : FreeCommRing α) : ∃ s : Finset α, IsSupported x ↑s :=
  let ⟨s, hfs, hxs⟩ := exists_finite_support x
  ⟨hfs.toFinset, by 

Proof state:
α : Type u
β : Type v
f : α → β
x : FreeCommRing α
s : Set α
hfs : Set.Finite s
hxs : IsSupported x s
⊢ IsSupported x ↑(Set.Finite.toFinset hfs)

Next tactic:
rwa [Set.Finite.coe_toFinset]
@[simp, norm_cast]
protected theorem coe_neg (x : FreeRing α) : ↑(-x) = -(x : FreeCommRing α) := by
  

Proof state:
α : Type u
x : FreeRing α
⊢ ↑(-x) = -↑x

Next tactic:
rw [castFreeCommRing, map_neg]
@[simp, norm_cast]
protected theorem coe_sub (x y : FreeRing α) : ↑(x - y) = (x : FreeCommRing α) - y := by
  

Proof state:
α : Type u
x y : FreeRing α
⊢ ↑(x - y) = ↑x - ↑y

Next tactic:
rw [castFreeCommRing, map_sub]
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  

Proof state:
α : Type u
x : FreeCommRing α
⊢ ∃ a, ↑a = x

Next tactic:
induction x using FreeCommRing.induction_on with
  | hn1 =>
    use -1
    rfl
  | hb b =>
    exact ⟨FreeRing.of b, rfl⟩
  | ha _ _ hx hy =>
    rcases hx with ⟨x, rfl⟩; rcases hy with ⟨y, rfl⟩
    exact ⟨x + y, (FreeRing.lift _).map_add _ _⟩
  | hm _ _ hx hy =>
    rcases hx with ⟨x, rfl⟩; rcases hy with ⟨y, rfl⟩
    exact ⟨x * y, (FreeRing.lift _).map_mul _ _⟩
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  

Proof state:
case hn1
α : Type u
⊢ ∃ a, ↑a = -1

Next tactic:
| hn1 =>
    use -1
    rfl
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  | hn1 =>
    

Proof state:
case hn1
α : Type u
⊢ ∃ a, ↑a = -1

Next tactic:
use -1
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  | hn1 =>
    use -1
    

Proof state:
case h
α : Type u
⊢ ↑(-1) = -1

Next tactic:
rfl
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  | hn1 =>
    use -1
    rfl
  

Proof state:
case hb
α : Type u
b : α
⊢ ∃ a, ↑a = FreeCommRing.of b

Next tactic:
| hb b =>
    exact ⟨FreeRing.of b, rfl⟩
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  | hn1 =>
    use -1
    rfl
  | hb b =>
    

Proof state:
case hb
α : Type u
b : α
⊢ ∃ a, ↑a = FreeCommRing.of b

Next tactic:
exact ⟨FreeRing.of b, rfl⟩
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  | hn1 =>
    use -1
    rfl
  | hb b =>
    exact ⟨FreeRing.of b, rfl⟩
  

Proof state:
case ha
α : Type u
x✝ y✝ : FreeCommRing α
hx : ∃ a, ↑a = x✝
hy : ∃ a, ↑a = y✝
⊢ ∃ a, ↑a = x✝ + y✝

Next tactic:
| ha _ _ hx hy =>
    rcases hx with ⟨x, rfl⟩; rcases hy with ⟨y, rfl⟩
    exact ⟨x + y, (FreeRing.lift _).map_add _ _⟩
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  | hn1 =>
    use -1
    rfl
  | hb b =>
    exact ⟨FreeRing.of b, rfl⟩
  | ha _ _ hx hy =>
    

Proof state:
case ha
α : Type u
x✝ y✝ : FreeCommRing α
hx : ∃ a, ↑a = x✝
hy : ∃ a, ↑a = y✝
⊢ ∃ a, ↑a = x✝ + y✝

Next tactic:
rcases hx with ⟨x, rfl⟩
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  | hn1 =>
    use -1
    rfl
  | hb b =>
    exact ⟨FreeRing.of b, rfl⟩
  | ha _ _ hx hy =>
    rcases hx with ⟨x, rfl⟩; 

Proof state:
case ha.intro
α : Type u
y✝ : FreeCommRing α
hy : ∃ a, ↑a = y✝
x : FreeRing α
⊢ ∃ a, ↑a = ↑x + y✝

Next tactic:
rcases hy with ⟨y, rfl⟩
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  | hn1 =>
    use -1
    rfl
  | hb b =>
    exact ⟨FreeRing.of b, rfl⟩
  | ha _ _ hx hy =>
    rcases hx with ⟨x, rfl⟩; rcases hy with ⟨y, rfl⟩
    

Proof state:
case ha.intro.intro
α : Type u
x y : FreeRing α
⊢ ∃ a, ↑a = ↑x + ↑y

Next tactic:
exact ⟨x + y, (FreeRing.lift _).map_add _ _⟩
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  | hn1 =>
    use -1
    rfl
  | hb b =>
    exact ⟨FreeRing.of b, rfl⟩
  | ha _ _ hx hy =>
    rcases hx with ⟨x, rfl⟩; rcases hy with ⟨y, rfl⟩
    exact ⟨x + y, (FreeRing.lift _).map_add _ _⟩
  

Proof state:
case hm
α : Type u
x✝ y✝ : FreeCommRing α
hx : ∃ a, ↑a = x✝
hy : ∃ a, ↑a = y✝
⊢ ∃ a, ↑a = x✝ * y✝

Next tactic:
| hm _ _ hx hy =>
    rcases hx with ⟨x, rfl⟩; rcases hy with ⟨y, rfl⟩
    exact ⟨x * y, (FreeRing.lift _).map_mul _ _⟩
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  | hn1 =>
    use -1
    rfl
  | hb b =>
    exact ⟨FreeRing.of b, rfl⟩
  | ha _ _ hx hy =>
    rcases hx with ⟨x, rfl⟩; rcases hy with ⟨y, rfl⟩
    exact ⟨x + y, (FreeRing.lift _).map_add _ _⟩
  | hm _ _ hx hy =>
    

Proof state:
case hm
α : Type u
x✝ y✝ : FreeCommRing α
hx : ∃ a, ↑a = x✝
hy : ∃ a, ↑a = y✝
⊢ ∃ a, ↑a = x✝ * y✝

Next tactic:
rcases hx with ⟨x, rfl⟩
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  | hn1 =>
    use -1
    rfl
  | hb b =>
    exact ⟨FreeRing.of b, rfl⟩
  | ha _ _ hx hy =>
    rcases hx with ⟨x, rfl⟩; rcases hy with ⟨y, rfl⟩
    exact ⟨x + y, (FreeRing.lift _).map_add _ _⟩
  | hm _ _ hx hy =>
    rcases hx with ⟨x, rfl⟩; 

Proof state:
case hm.intro
α : Type u
y✝ : FreeCommRing α
hy : ∃ a, ↑a = y✝
x : FreeRing α
⊢ ∃ a, ↑a = ↑x * y✝

Next tactic:
rcases hy with ⟨y, rfl⟩
protected theorem coe_surjective : Surjective ((↑) : FreeRing α → FreeCommRing α) := fun x => by
  induction x using FreeCommRing.induction_on with
  | hn1 =>
    use -1
    rfl
  | hb b =>
    exact ⟨FreeRing.of b, rfl⟩
  | ha _ _ hx hy =>
    rcases hx with ⟨x, rfl⟩; rcases hy with ⟨y, rfl⟩
    exact ⟨x + y, (FreeRing.lift _).map_add _ _⟩
  | hm _ _ hx hy =>
    rcases hx with ⟨x, rfl⟩; rcases hy with ⟨y, rfl⟩
    

Proof state:
case hm.intro.intro
α : Type u
x y : FreeRing α
⊢ ∃ a, ↑a = ↑x * ↑y

Next tactic:
exact ⟨x * y, (FreeRing.lift _).map_mul _ _⟩
theorem coe_eq : ((↑) : FreeRing α → FreeCommRing α) =
    @Functor.map FreeAbelianGroup _ _ _ fun l : List α => (l : Multiset α) := by
  

Proof state:
α : Type u
⊢ castFreeCommRing = Functor.map fun l => ↑l

Next tactic:
funext x
theorem coe_eq : ((↑) : FreeRing α → FreeCommRing α) =
    @Functor.map FreeAbelianGroup _ _ _ fun l : List α => (l : Multiset α) := by
  funext x
  

Proof state:
case h
α : Type u
x : FreeRing α
⊢ ↑x = (fun l => ↑l) <$> x

Next tactic:
erw [castFreeCommRing, toFreeCommRing, FreeRing.lift, Equiv.coe_trans, Function.comp,
    FreeAbelianGroup.liftMonoid_coe (FreeMonoid.lift FreeCommRing.of)]
theorem coe_eq : ((↑) : FreeRing α → FreeCommRing α) =
    @Functor.map FreeAbelianGroup _ _ _ fun l : List α => (l : Multiset α) := by
  funext x
  erw [castFreeCommRing, toFreeCommRing, FreeRing.lift, Equiv.coe_trans, Function.comp,
    FreeAbelianGroup.liftMonoid_coe (FreeMonoid.lift FreeCommRing.of)]
  

Proof state:
case h
α : Type u
x : FreeRing α
⊢ (FreeAbelianGroup.lift ⇑(FreeMonoid.lift FreeCommRing.of)) x = (fun l => ↑l) <$> x

Next tactic:
dsimp [Functor.map]
theorem coe_eq : ((↑) : FreeRing α → FreeCommRing α) =
    @Functor.map FreeAbelianGroup _ _ _ fun l : List α => (l : Multiset α) := by
  funext x
  erw [castFreeCommRing, toFreeCommRing, FreeRing.lift, Equiv.coe_trans, Function.comp,
    FreeAbelianGroup.liftMonoid_coe (FreeMonoid.lift FreeCommRing.of)]
  dsimp [Functor.map]
  

Proof state:
case h
α : Type u
x : FreeRing α
⊢ (FreeAbelianGroup.lift ⇑(FreeMonoid.lift FreeCommRing.of)) x =
    (FreeAbelianGroup.lift ((fun α_1 => FreeAbelianGroup.of α_1) ∘ fun l => ↑l)) x

Next tactic:
rw [← AddMonoidHom.coe_coe]
theorem coe_eq : ((↑) : FreeRing α → FreeCommRing α) =
    @Functor.map FreeAbelianGroup _ _ _ fun l : List α => (l : Multiset α) := by
  funext x
  erw [castFreeCommRing, toFreeCommRing, FreeRing.lift, Equiv.coe_trans, Function.comp,
    FreeAbelianGroup.liftMonoid_coe (FreeMonoid.lift FreeCommRing.of)]
  dsimp [Functor.map]
  rw [← AddMonoidHom.coe_coe]
  

Proof state:
case h
α : Type u
x : FreeRing α
⊢ ↑(FreeAbelianGroup.lift ⇑(FreeMonoid.lift FreeCommRing.of)) x =
    (FreeAbelianGroup.lift ((fun α_1 => FreeAbelianGroup.of α_1) ∘ fun l => ↑l)) x

Next tactic:
apply FreeAbelianGroup.lift.unique
theorem coe_eq : ((↑) : FreeRing α → FreeCommRing α) =
    @Functor.map FreeAbelianGroup _ _ _ fun l : List α => (l : Multiset α) := by
  funext x
  erw [castFreeCommRing, toFreeCommRing, FreeRing.lift, Equiv.coe_trans, Function.comp,
    FreeAbelianGroup.liftMonoid_coe (FreeMonoid.lift FreeCommRing.of)]
  dsimp [Functor.map]
  rw [← AddMonoidHom.coe_coe]
  apply FreeAbelianGroup.lift.unique; 

Proof state:
case h.hg
α : Type u
x : FreeRing α
⊢ ∀ (x : FreeMonoid α),
    ↑(FreeAbelianGroup.lift ⇑(FreeMonoid.lift FreeCommRing.of)) (FreeAbelianGroup.of x) =
      ((fun α_1 => FreeAbelianGroup.of α_1) ∘ fun l => ↑l) x

Next tactic:
intro L
theorem coe_eq : ((↑) : FreeRing α → FreeCommRing α) =
    @Functor.map FreeAbelianGroup _ _ _ fun l : List α => (l : Multiset α) := by
  funext x
  erw [castFreeCommRing, toFreeCommRing, FreeRing.lift, Equiv.coe_trans, Function.comp,
    FreeAbelianGroup.liftMonoid_coe (FreeMonoid.lift FreeCommRing.of)]
  dsimp [Functor.map]
  rw [← AddMonoidHom.coe_coe]
  apply FreeAbelianGroup.lift.unique; intro L
  

Proof state:
case h.hg
α : Type u
x : FreeRing α
L : FreeMonoid α
⊢ ↑(FreeAbelianGroup.lift ⇑(FreeMonoid.lift FreeCommRing.of)) (FreeAbelianGroup.of L) =
    ((fun α_1 => FreeAbelianGroup.of α_1) ∘ fun l => ↑l) L

Next tactic:
erw [FreeAbelianGroup.lift.of, Function.comp]
theorem coe_eq : ((↑) : FreeRing α → FreeCommRing α) =
    @Functor.map FreeAbelianGroup _ _ _ fun l : List α => (l : Multiset α) := by
  funext x
  erw [castFreeCommRing, toFreeCommRing, FreeRing.lift, Equiv.coe_trans, Function.comp,
    FreeAbelianGroup.liftMonoid_coe (FreeMonoid.lift FreeCommRing.of)]
  dsimp [Functor.map]
  rw [← AddMonoidHom.coe_coe]
  apply FreeAbelianGroup.lift.unique; intro L
  erw [FreeAbelianGroup.lift.of, Function.comp]
  

Proof state:
case h.hg
α : Type u
x : FreeRing α
L : FreeMonoid α
⊢ (FreeMonoid.lift FreeCommRing.of) L = (fun x => FreeAbelianGroup.of ↑x) L

Next tactic:
exact
    FreeMonoid.recOn L rfl fun hd tl ih => by
      rw [(FreeMonoid.lift _).map_mul, FreeMonoid.lift_eval_of, ih]
      conv_lhs => reduce
theorem coe_eq : ((↑) : FreeRing α → FreeCommRing α) =
    @Functor.map FreeAbelianGroup _ _ _ fun l : List α => (l : Multiset α) := by
  funext x
  erw [castFreeCommRing, toFreeCommRing, FreeRing.lift, Equiv.coe_trans, Function.comp,
    FreeAbelianGroup.liftMonoid_coe (FreeMonoid.lift FreeCommRing.of)]
  dsimp [Functor.map]
  rw [← AddMonoidHom.coe_coe]
  apply FreeAbelianGroup.lift.unique; intro L
  erw [FreeAbelianGroup.lift.of, Function.comp]
  exact
    FreeMonoid.recOn L rfl fun hd tl ih => by
      

Proof state:
α : Type u
x : FreeRing α
L : FreeMonoid α
hd : α
tl : FreeMonoid α
ih : (FreeMonoid.lift FreeCommRing.of) tl = (fun x => FreeAbelianGroup.of ↑x) tl
⊢ (FreeMonoid.lift FreeCommRing.of) (FreeMonoid.of hd * tl) = (fun x => FreeAbelianGroup.of ↑x) (FreeMonoid.of hd * tl)

Next tactic:
rw [(FreeMonoid.lift _).map_mul, FreeMonoid.lift_eval_of, ih]