l3lab/ntp-mathlib huggingface dataset:
instance : LawfulMonad FreeAbelianGroup.{u} := LawfulMonad.mk'
  (id_map := fun x ↦ FreeAbelianGroup.induction_on' x (FreeAbelianGroup.map_zero id) (map_pure id)
    (fun x ih ↦ by rw [FreeAbelianGroup.map_neg, ih])
    fun x y ihx ihy ↦ by rw [FreeAbelianGroup.map_add, ihx, ihy])
  (pure_bind := fun x f ↦ pure_bind f x)
  (bind_assoc := fun x f g ↦ FreeAbelianGroup.induction_on' x (by iterate 3 rw [zero_bind])
    (fun x ↦ by iterate 2 rw [pure_bind]) (fun x ih ↦ by iterate 3 rw [neg_bind] <;> try rw [ih])
    fun x y ihx ihy ↦ by iterate 3 rw [add_bind] <;> 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x y : FreeAbelianGroup α✝
ihx : x >>= f >>= g = x >>= fun x => f x >>= g
ihy : y >>= f >>= g = y >>= fun x => f x >>= g
⊢ (x >>= f >>= g) + (y >>= f >>= g) = x + y >>= fun x => f x >>= g

Next tactic:
try rw [ihx, ihy]
instance : LawfulMonad FreeAbelianGroup.{u} := LawfulMonad.mk'
  (id_map := fun x ↦ FreeAbelianGroup.induction_on' x (FreeAbelianGroup.map_zero id) (map_pure id)
    (fun x ih ↦ by rw [FreeAbelianGroup.map_neg, ih])
    fun x y ihx ihy ↦ by rw [FreeAbelianGroup.map_add, ihx, ihy])
  (pure_bind := fun x f ↦ pure_bind f x)
  (bind_assoc := fun x f g ↦ FreeAbelianGroup.induction_on' x (by iterate 3 rw [zero_bind])
    (fun x ↦ by iterate 2 rw [pure_bind]) (fun x ih ↦ by iterate 3 rw [neg_bind] <;> try rw [ih])
    fun x y ihx ihy ↦ by iterate 3 rw [add_bind] <;> try 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x y : FreeAbelianGroup α✝
ihx : x >>= f >>= g = x >>= fun x => f x >>= g
ihy : y >>= f >>= g = y >>= fun x => f x >>= g
⊢ (x >>= f >>= g) + (y >>= f >>= g) = x + y >>= fun x => f x >>= g

Next tactic:
rw [ihx, ihy]
instance : LawfulMonad FreeAbelianGroup.{u} := LawfulMonad.mk'
  (id_map := fun x ↦ FreeAbelianGroup.induction_on' x (FreeAbelianGroup.map_zero id) (map_pure id)
    (fun x ih ↦ by rw [FreeAbelianGroup.map_neg, ih])
    fun x y ihx ihy ↦ by rw [FreeAbelianGroup.map_add, ihx, ihy])
  (pure_bind := fun x f ↦ pure_bind f x)
  (bind_assoc := fun x f g ↦ FreeAbelianGroup.induction_on' x (by iterate 3 rw [zero_bind])
    (fun x ↦ by iterate 2 rw [pure_bind]) (fun x ih ↦ by iterate 3 rw [neg_bind] <;> try rw [ih])
    fun x y ihx ihy ↦ by iterate 3 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x y : FreeAbelianGroup α✝
ihx : x >>= f >>= g = x >>= fun x => f x >>= g
ihy : y >>= f >>= g = y >>= fun x => f x >>= g
⊢ (x >>= fun x => f x >>= g) + (y >>= fun x => f x >>= g) = x + y >>= fun x => f x >>= g

Next tactic:
rw [add_bind]
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    

Proof state:
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
⊢ (Seq.seq (Prod.mk <$> x) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x_1 => x

Next tactic:
refine' FreeAbelianGroup.induction_on' x _ _ _ _
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    refine' FreeAbelianGroup.induction_on' x _ _ _ _
    · 

Proof state:
case refine'_1
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
⊢ (Seq.seq (Prod.mk <$> 0) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x => 0

Next tactic:
rw [FreeAbelianGroup.map_zero, zero_seq, seq_zero]
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    refine' FreeAbelianGroup.induction_on' x _ _ _ _
    · rw [FreeAbelianGroup.map_zero, zero_seq, seq_zero]
    · 

Proof state:
case refine'_2
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
⊢ ∀ (x : α✝), (Seq.seq (Prod.mk <$> pure x) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x_1 => pure x

Next tactic:
intro p
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    refine' FreeAbelianGroup.induction_on' x _ _ _ _
    · rw [FreeAbelianGroup.map_zero, zero_seq, seq_zero]
    · intro p
      

Proof state:
case refine'_2
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
p : α✝
⊢ (Seq.seq (Prod.mk <$> pure p) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x => pure p

Next tactic:
rw [map_pure, pure_seq]
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    refine' FreeAbelianGroup.induction_on' x _ _ _ _
    · rw [FreeAbelianGroup.map_zero, zero_seq, seq_zero]
    · intro p
      rw [map_pure, pure_seq]
      

Proof state:
case refine'_2
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
p : α✝
⊢ Prod.mk p <$> y = Seq.seq ((fun b a => (a, b)) <$> y) fun x => pure p

Next tactic:
exact FreeAbelianGroup.induction_on' y
        (by rw [FreeAbelianGroup.map_zero, FreeAbelianGroup.map_zero, zero_seq])
        (fun q ↦ by rw [map_pure, map_pure, pure_seq, map_pure])
        (fun q ih ↦ by rw [FreeAbelianGroup.map_neg, FreeAbelianGroup.map_neg, neg_seq, ih])
        fun y₁ y₂ ih1 ih2 ↦ by
          rw [FreeAbelianGroup.map_add, FreeAbelianGroup.map_add, add_seq, ih1, ih2]
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    refine' FreeAbelianGroup.induction_on' x _ _ _ _
    · rw [FreeAbelianGroup.map_zero, zero_seq, seq_zero]
    · intro p
      rw [map_pure, pure_seq]
      exact FreeAbelianGroup.induction_on' y
        (by 

Proof state:
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
p : α✝
⊢ Prod.mk p <$> 0 = Seq.seq ((fun b a => (a, b)) <$> 0) fun x => pure p

Next tactic:
rw [FreeAbelianGroup.map_zero, FreeAbelianGroup.map_zero, zero_seq]
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    refine' FreeAbelianGroup.induction_on' x _ _ _ _
    · rw [FreeAbelianGroup.map_zero, zero_seq, seq_zero]
    · intro p
      rw [map_pure, pure_seq]
      exact FreeAbelianGroup.induction_on' y
        (by rw [FreeAbelianGroup.map_zero, FreeAbelianGroup.map_zero, zero_seq])
        (fun q ↦ by 

Proof state:
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
p : α✝
q : β✝
⊢ Prod.mk p <$> pure q = Seq.seq ((fun b a => (a, b)) <$> pure q) fun x => pure p

Next tactic:
rw [map_pure, map_pure, pure_seq, map_pure]
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    refine' FreeAbelianGroup.induction_on' x _ _ _ _
    · rw [FreeAbelianGroup.map_zero, zero_seq, seq_zero]
    · intro p
      rw [map_pure, pure_seq]
      exact FreeAbelianGroup.induction_on' y
        (by rw [FreeAbelianGroup.map_zero, FreeAbelianGroup.map_zero, zero_seq])
        (fun q ↦ by rw [map_pure, map_pure, pure_seq, map_pure])
        (fun q ih ↦ by 

Proof state:
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
p : α✝
q : β✝
ih : Prod.mk p <$> pure q = Seq.seq ((fun b a => (a, b)) <$> pure q) fun x => pure p
⊢ Prod.mk p <$> (-pure q) = Seq.seq ((fun b a => (a, b)) <$> (-pure q)) fun x => pure p

Next tactic:
rw [FreeAbelianGroup.map_neg, FreeAbelianGroup.map_neg, neg_seq, ih]
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    refine' FreeAbelianGroup.induction_on' x _ _ _ _
    · rw [FreeAbelianGroup.map_zero, zero_seq, seq_zero]
    · intro p
      rw [map_pure, pure_seq]
      exact FreeAbelianGroup.induction_on' y
        (by rw [FreeAbelianGroup.map_zero, FreeAbelianGroup.map_zero, zero_seq])
        (fun q ↦ by rw [map_pure, map_pure, pure_seq, map_pure])
        (fun q ih ↦ by rw [FreeAbelianGroup.map_neg, FreeAbelianGroup.map_neg, neg_seq, ih])
        fun y₁ y₂ ih1 ih2 ↦ by
          

Proof state:
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
p : α✝
y₁ y₂ : FreeAbelianGroup β✝
ih1 : Prod.mk p <$> y₁ = Seq.seq ((fun b a => (a, b)) <$> y₁) fun x => pure p
ih2 : Prod.mk p <$> y₂ = Seq.seq ((fun b a => (a, b)) <$> y₂) fun x => pure p
⊢ Prod.mk p <$> (y₁ + y₂) = Seq.seq ((fun b a => (a, b)) <$> (y₁ + y₂)) fun x => pure p

Next tactic:
rw [FreeAbelianGroup.map_add, FreeAbelianGroup.map_add, add_seq, ih1, ih2]
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    refine' FreeAbelianGroup.induction_on' x _ _ _ _
    · rw [FreeAbelianGroup.map_zero, zero_seq, seq_zero]
    · intro p
      rw [map_pure, pure_seq]
      exact FreeAbelianGroup.induction_on' y
        (by rw [FreeAbelianGroup.map_zero, FreeAbelianGroup.map_zero, zero_seq])
        (fun q ↦ by rw [map_pure, map_pure, pure_seq, map_pure])
        (fun q ih ↦ by rw [FreeAbelianGroup.map_neg, FreeAbelianGroup.map_neg, neg_seq, ih])
        fun y₁ y₂ ih1 ih2 ↦ by
          rw [FreeAbelianGroup.map_add, FreeAbelianGroup.map_add, add_seq, ih1, ih2]
    · 

Proof state:
case refine'_3
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
⊢ ∀ (x : α✝),
    ((Seq.seq (Prod.mk <$> pure x) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x_1 => pure x) →
      (Seq.seq (Prod.mk <$> (-pure x)) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x_1 => -pure x

Next tactic:
intro p ih
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    refine' FreeAbelianGroup.induction_on' x _ _ _ _
    · rw [FreeAbelianGroup.map_zero, zero_seq, seq_zero]
    · intro p
      rw [map_pure, pure_seq]
      exact FreeAbelianGroup.induction_on' y
        (by rw [FreeAbelianGroup.map_zero, FreeAbelianGroup.map_zero, zero_seq])
        (fun q ↦ by rw [map_pure, map_pure, pure_seq, map_pure])
        (fun q ih ↦ by rw [FreeAbelianGroup.map_neg, FreeAbelianGroup.map_neg, neg_seq, ih])
        fun y₁ y₂ ih1 ih2 ↦ by
          rw [FreeAbelianGroup.map_add, FreeAbelianGroup.map_add, add_seq, ih1, ih2]
    · intro p ih
      

Proof state:
case refine'_3
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
p : α✝
ih : (Seq.seq (Prod.mk <$> pure p) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x => pure p
⊢ (Seq.seq (Prod.mk <$> (-pure p)) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x => -pure p

Next tactic:
rw [FreeAbelianGroup.map_neg, neg_seq, seq_neg, ih]
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    refine' FreeAbelianGroup.induction_on' x _ _ _ _
    · rw [FreeAbelianGroup.map_zero, zero_seq, seq_zero]
    · intro p
      rw [map_pure, pure_seq]
      exact FreeAbelianGroup.induction_on' y
        (by rw [FreeAbelianGroup.map_zero, FreeAbelianGroup.map_zero, zero_seq])
        (fun q ↦ by rw [map_pure, map_pure, pure_seq, map_pure])
        (fun q ih ↦ by rw [FreeAbelianGroup.map_neg, FreeAbelianGroup.map_neg, neg_seq, ih])
        fun y₁ y₂ ih1 ih2 ↦ by
          rw [FreeAbelianGroup.map_add, FreeAbelianGroup.map_add, add_seq, ih1, ih2]
    · intro p ih
      rw [FreeAbelianGroup.map_neg, neg_seq, seq_neg, ih]
    · 

Proof state:
case refine'_4
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
⊢ ∀ (x y_1 : FreeAbelianGroup α✝),
    ((Seq.seq (Prod.mk <$> x) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x_1 => x) →
      ((Seq.seq (Prod.mk <$> y_1) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x => y_1) →
        (Seq.seq (Prod.mk <$> (x + y_1)) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x_1 => x + y_1

Next tactic:
intro x₁ x₂ ih1 ih2
instance : CommApplicative FreeAbelianGroup.{u} where
  commutative_prod x y := by
    refine' FreeAbelianGroup.induction_on' x _ _ _ _
    · rw [FreeAbelianGroup.map_zero, zero_seq, seq_zero]
    · intro p
      rw [map_pure, pure_seq]
      exact FreeAbelianGroup.induction_on' y
        (by rw [FreeAbelianGroup.map_zero, FreeAbelianGroup.map_zero, zero_seq])
        (fun q ↦ by rw [map_pure, map_pure, pure_seq, map_pure])
        (fun q ih ↦ by rw [FreeAbelianGroup.map_neg, FreeAbelianGroup.map_neg, neg_seq, ih])
        fun y₁ y₂ ih1 ih2 ↦ by
          rw [FreeAbelianGroup.map_add, FreeAbelianGroup.map_add, add_seq, ih1, ih2]
    · intro p ih
      rw [FreeAbelianGroup.map_neg, neg_seq, seq_neg, ih]
    · intro x₁ x₂ ih1 ih2
      

Proof state:
case refine'_4
α β α✝ β✝ : Type u
x : FreeAbelianGroup α✝
y : FreeAbelianGroup β✝
x₁ x₂ : FreeAbelianGroup α✝
ih1 : (Seq.seq (Prod.mk <$> x₁) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x => x₁
ih2 : (Seq.seq (Prod.mk <$> x₂) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x => x₂
⊢ (Seq.seq (Prod.mk <$> (x₁ + x₂)) fun x => y) = Seq.seq ((fun b a => (a, b)) <$> y) fun x => x₁ + x₂

Next tactic:
rw [FreeAbelianGroup.map_add, add_seq, seq_add, ih1, ih2]
theorem lift_comp {α} {β} {γ} [AddCommGroup γ] (f : α → β) (g : β → γ) (x : FreeAbelianGroup α) :
    lift (g ∘ f) x = lift g (map f x) := by
  -- Porting note: Added motive.
  

Proof state:
α✝ : Type u
β✝ : Type v
γ✝ : Type w
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : AddCommGroup γ
f : α → β
g : β → γ
x : FreeAbelianGroup α
⊢ (lift (g ∘ f)) x = (lift g) ((map f) x)

Next tactic:
apply FreeAbelianGroup.induction_on (C := fun x ↦ lift (g ∘ f) x = lift g (map f x)) x
theorem lift_comp {α} {β} {γ} [AddCommGroup γ] (f : α → β) (g : β → γ) (x : FreeAbelianGroup α) :
    lift (g ∘ f) x = lift g (map f x) := by
  -- Porting note: Added motive.
  apply FreeAbelianGroup.induction_on (C := fun x ↦ lift (g ∘ f) x = lift g (map f x)) x
  · 

Proof state:
case C0
α✝ : Type u
β✝ : Type v
γ✝ : Type w
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : AddCommGroup γ
f : α → β
g : β → γ
x : FreeAbelianGroup α
⊢ (lift (g ∘ f)) 0 = (lift g) ((map f) 0)

Next tactic:
simp only [map_zero]
theorem lift_comp {α} {β} {γ} [AddCommGroup γ] (f : α → β) (g : β → γ) (x : FreeAbelianGroup α) :
    lift (g ∘ f) x = lift g (map f x) := by
  -- Porting note: Added motive.
  apply FreeAbelianGroup.induction_on (C := fun x ↦ lift (g ∘ f) x = lift g (map f x)) x
  · simp only [map_zero]
  · 

Proof state:
case C1
α✝ : Type u
β✝ : Type v
γ✝ : Type w
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : AddCommGroup γ
f : α → β
g : β → γ
x : FreeAbelianGroup α
⊢ ∀ (x : α), (lift (g ∘ f)) (of x) = (lift g) ((map f) (of x))

Next tactic:
intro _
theorem lift_comp {α} {β} {γ} [AddCommGroup γ] (f : α → β) (g : β → γ) (x : FreeAbelianGroup α) :
    lift (g ∘ f) x = lift g (map f x) := by
  -- Porting note: Added motive.
  apply FreeAbelianGroup.induction_on (C := fun x ↦ lift (g ∘ f) x = lift g (map f x)) x
  · simp only [map_zero]
  · intro _
    

Proof state:
case C1
α✝ : Type u
β✝ : Type v
γ✝ : Type w
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : AddCommGroup γ
f : α → β
g : β → γ
x : FreeAbelianGroup α
x✝ : α
⊢ (lift (g ∘ f)) (of x✝) = (lift g) ((map f) (of x✝))

Next tactic:
simp only [lift.of, map, Function.comp]
theorem lift_comp {α} {β} {γ} [AddCommGroup γ] (f : α → β) (g : β → γ) (x : FreeAbelianGroup α) :
    lift (g ∘ f) x = lift g (map f x) := by
  -- Porting note: Added motive.
  apply FreeAbelianGroup.induction_on (C := fun x ↦ lift (g ∘ f) x = lift g (map f x)) x
  · simp only [map_zero]
  · intro _
    simp only [lift.of, map, Function.comp]
  · 

Proof state:
case Cn
α✝ : Type u
β✝ : Type v
γ✝ : Type w
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : AddCommGroup γ
f : α → β
g : β → γ
x : FreeAbelianGroup α
⊢ ∀ (x : α), (lift (g ∘ f)) (of x) = (lift g) ((map f) (of x)) → (lift (g ∘ f)) (-of x) = (lift g) ((map f) (-of x))

Next tactic:
intro _ h
theorem lift_comp {α} {β} {γ} [AddCommGroup γ] (f : α → β) (g : β → γ) (x : FreeAbelianGroup α) :
    lift (g ∘ f) x = lift g (map f x) := by
  -- Porting note: Added motive.
  apply FreeAbelianGroup.induction_on (C := fun x ↦ lift (g ∘ f) x = lift g (map f x)) x
  · simp only [map_zero]
  · intro _
    simp only [lift.of, map, Function.comp]
  · intro _ h
    

Proof state:
case Cn
α✝ : Type u
β✝ : Type v
γ✝ : Type w
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : AddCommGroup γ
f : α → β
g : β → γ
x : FreeAbelianGroup α
x✝ : α
h : (lift (g ∘ f)) (of x✝) = (lift g) ((map f) (of x✝))
⊢ (lift (g ∘ f)) (-of x✝) = (lift g) ((map f) (-of x✝))

Next tactic:
simp only [h, AddMonoidHom.map_neg]
theorem lift_comp {α} {β} {γ} [AddCommGroup γ] (f : α → β) (g : β → γ) (x : FreeAbelianGroup α) :
    lift (g ∘ f) x = lift g (map f x) := by
  -- Porting note: Added motive.
  apply FreeAbelianGroup.induction_on (C := fun x ↦ lift (g ∘ f) x = lift g (map f x)) x
  · simp only [map_zero]
  · intro _
    simp only [lift.of, map, Function.comp]
  · intro _ h
    simp only [h, AddMonoidHom.map_neg]
  · 

Proof state:
case Cp
α✝ : Type u
β✝ : Type v
γ✝ : Type w
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : AddCommGroup γ
f : α → β
g : β → γ
x : FreeAbelianGroup α
⊢ ∀ (x y : FreeAbelianGroup α),
    (lift (g ∘ f)) x = (lift g) ((map f) x) →
      (lift (g ∘ f)) y = (lift g) ((map f) y) → (lift (g ∘ f)) (x + y) = (lift g) ((map f) (x + y))

Next tactic:
intro _ _ h₁ h₂
theorem lift_comp {α} {β} {γ} [AddCommGroup γ] (f : α → β) (g : β → γ) (x : FreeAbelianGroup α) :
    lift (g ∘ f) x = lift g (map f x) := by
  -- Porting note: Added motive.
  apply FreeAbelianGroup.induction_on (C := fun x ↦ lift (g ∘ f) x = lift g (map f x)) x
  · simp only [map_zero]
  · intro _
    simp only [lift.of, map, Function.comp]
  · intro _ h
    simp only [h, AddMonoidHom.map_neg]
  · intro _ _ h₁ h₂
    

Proof state:
case Cp
α✝ : Type u
β✝ : Type v
γ✝ : Type w
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝ : AddCommGroup γ
f : α → β
g : β → γ
x x✝ y✝ : FreeAbelianGroup α
h₁ : (lift (g ∘ f)) x✝ = (lift g) ((map f) x✝)
h₂ : (lift (g ∘ f)) y✝ = (lift g) ((map f) y✝)
⊢ (lift (g ∘ f)) (x✝ + y✝) = (lift g) ((map f) (x✝ + y✝))

Next tactic:
simp only [h₁, h₂, AddMonoidHom.map_add]
theorem map_id_apply (x : FreeAbelianGroup α) : map id x = x := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
x : FreeAbelianGroup α
⊢ (map id) x = x

Next tactic:
rw [map_id]
theorem map_id_apply (x : FreeAbelianGroup α) : map id x = x := by
  rw [map_id]
  

Proof state:
α : Type u
β : Type v
γ : Type w
x : FreeAbelianGroup α
⊢ (AddMonoidHom.id (FreeAbelianGroup α)) x = x

Next tactic:
rfl
theorem map_comp {f : α → β} {g : β → γ} : map (g ∘ f) = (map g).comp (map f) :=
  Eq.symm <| lift.ext _ _ fun _ ↦ by 

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
g : β → γ
x✝ : α
⊢ (AddMonoidHom.comp (map g) (map f)) (of x✝) = (map (g ∘ f)) (of x✝)

Next tactic:
simp [map]
theorem map_comp_apply {f : α → β} {g : β → γ} (x : FreeAbelianGroup α) :
    map (g ∘ f) x = (map g) ((map f) x) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
g : β → γ
x : FreeAbelianGroup α
⊢ (map (g ∘ f)) x = (map g) ((map f) x)

Next tactic:
rw [map_comp]
theorem map_comp_apply {f : α → β} {g : β → γ} (x : FreeAbelianGroup α) :
    map (g ∘ f) x = (map g) ((map f) x) := by
  rw [map_comp]
  

Proof state:
α : Type u
β : Type v
γ : Type w
f : α → β
g : β → γ
x : FreeAbelianGroup α
⊢ (AddMonoidHom.comp (map g) (map f)) x = (map g) ((map f) x)

Next tactic:
rfl
@[simp]
theorem of_mul_of (x y : α) : of x * of y = of (x * y) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝ : Mul α
x y : α
⊢ of x * of y = of (x * y)

Next tactic:
rw [mul_def, lift.of, lift.of]
instance distrib : Distrib (FreeAbelianGroup α) :=
  { FreeAbelianGroup.mul α, FreeAbelianGroup.addCommGroup α with
    left_distrib := fun x y z ↦ (lift _).map_add _ _
    right_distrib := fun x y z ↦ by 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝ : Mul α
src✝¹ : Mul (FreeAbelianGroup α) := mul α
src✝ : AddCommGroup (FreeAbelianGroup α) := addCommGroup α
x y z : FreeAbelianGroup α
⊢ (x + y) * z = x * z + y * z

Next tactic:
simp only [(· * ·), Mul.mul, map_add, ← Pi.add_def, lift.add']
instance nonUnitalNonAssocRing : NonUnitalNonAssocRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.distrib,
    FreeAbelianGroup.addCommGroup _ with
    zero_mul := fun a ↦ by
      

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝ : Mul α
src✝¹ : Distrib (FreeAbelianGroup α) := distrib
src✝ : AddCommGroup (FreeAbelianGroup α) := addCommGroup α
a : FreeAbelianGroup α
⊢ 0 * a = 0

Next tactic:
have h : 0 * a + 0 * a = 0 * a := by simp [← add_mul]
instance nonUnitalNonAssocRing : NonUnitalNonAssocRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.distrib,
    FreeAbelianGroup.addCommGroup _ with
    zero_mul := fun a ↦ by
      have h : 0 * a + 0 * a = 0 * a := by 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝ : Mul α
src✝¹ : Distrib (FreeAbelianGroup α) := distrib
src✝ : AddCommGroup (FreeAbelianGroup α) := addCommGroup α
a : FreeAbelianGroup α
⊢ 0 * a + 0 * a = 0 * a

Next tactic:
simp [← add_mul]
instance nonUnitalNonAssocRing : NonUnitalNonAssocRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.distrib,
    FreeAbelianGroup.addCommGroup _ with
    zero_mul := fun a ↦ by
      have h : 0 * a + 0 * a = 0 * a := by simp [← add_mul]
      

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝ : Mul α
src✝¹ : Distrib (FreeAbelianGroup α) := distrib
src✝ : AddCommGroup (FreeAbelianGroup α) := addCommGroup α
a : FreeAbelianGroup α
h : 0 * a + 0 * a = 0 * a
⊢ 0 * a = 0

Next tactic:
simpa using h
instance nonUnitalRing [Semigroup α] : NonUnitalRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.nonUnitalNonAssocRing with
    mul_assoc := fun x y z ↦ by
      

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝ : Semigroup α
src✝ : NonUnitalNonAssocRing (FreeAbelianGroup α) := nonUnitalNonAssocRing
x y z : FreeAbelianGroup α
⊢ x * y * z = x * (y * z)

Next tactic:
refine' FreeAbelianGroup.induction_on z (by simp only [mul_zero])
          (fun L3 ↦ _) (fun L3 ih ↦ _) fun z₁ z₂ ih₁ ih₂ ↦ _
instance nonUnitalRing [Semigroup α] : NonUnitalRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.nonUnitalNonAssocRing with
    mul_assoc := fun x y z ↦ by
      refine' FreeAbelianGroup.induction_on z (by 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝ : Semigroup α
src✝ : NonUnitalNonAssocRing (FreeAbelianGroup α) := nonUnitalNonAssocRing
x y z : FreeAbelianGroup α
⊢ x * y * 0 = x * (y * 0)

Next tactic:
simp only [mul_zero]
instance nonUnitalRing [Semigroup α] : NonUnitalRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.nonUnitalNonAssocRing with
    mul_assoc := fun x y z ↦ by
      refine' FreeAbelianGroup.induction_on z (by simp only [mul_zero])
          (fun L3 ↦ _) (fun L3 ih ↦ _) fun z₁ z₂ ih₁ ih₂ ↦ _
      · 

Proof state:
case refine'_1
α : Type u
β : Type v
γ : Type w
inst✝ : Semigroup α
src✝ : NonUnitalNonAssocRing (FreeAbelianGroup α) := nonUnitalNonAssocRing
x y z : FreeAbelianGroup α
L3 : α
⊢ x * y * of L3 = x * (y * of L3)

Next tactic:
refine' FreeAbelianGroup.induction_on y (by simp only [mul_zero, zero_mul])
            (fun L2 ↦ _) (fun L2 ih ↦ _) fun y₁ y₂ ih₁ ih₂ ↦ _
instance nonUnitalRing [Semigroup α] : NonUnitalRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.nonUnitalNonAssocRing with
    mul_assoc := fun x y z ↦ by
      refine' FreeAbelianGroup.induction_on z (by simp only [mul_zero])
          (fun L3 ↦ _) (fun L3 ih ↦ _) fun z₁ z₂ ih₁ ih₂ ↦ _
      · refine' FreeAbelianGroup.induction_on y (by 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝ : Semigroup α
src✝ : NonUnitalNonAssocRing (FreeAbelianGroup α) := nonUnitalNonAssocRing
x y z : FreeAbelianGroup α
L3 : α
⊢ x * 0 * of L3 = x * (0 * of L3)

Next tactic:
simp only [mul_zero, zero_mul]
instance nonUnitalRing [Semigroup α] : NonUnitalRing (FreeAbelianGroup α) :=
  { FreeAbelianGroup.nonUnitalNonAssocRing with
    mul_assoc := fun x y z ↦ by
      refine' FreeAbelianGroup.induction_on z (by simp only [mul_zero])
          (fun L3 ↦ _) (fun L3 ih ↦ _) fun z₁ z₂ ih₁ ih₂ ↦ _
      · refine' FreeAbelianGroup.induction_on y (by simp only [mul_zero, zero_mul])
            (fun L2 ↦ _) (fun L2 ih ↦ _) fun y₁ y₂ ih₁ ih₂ ↦ _
        · 

Proof state:
case refine'_1.refine'_1
α : Type u
β : Type v
γ : Type w
inst✝ : Semigroup α
src✝ : NonUnitalNonAssocRing (FreeAbelianGroup α) := nonUnitalNonAssocRing
x y z : FreeAbelianGroup α
L3 L2 : α
⊢ x * of L2 * of L3 = x * (of L2 * of L3)

Next tactic:
refine' FreeAbelianGroup.induction_on x (by simp only [zero_mul])
              (fun L1 ↦ _) (fun L1 ih ↦ _) fun x₁ x₂ ih₁ ih₂ ↦ _