l3lab/ntp-mathlib huggingface dataset:
@[simp]
protected theorem of (x : α) : lift f (of x) = f x := by
  

Proof state:
α : Type u
β : Type v
inst✝ : AddCommGroup β
f : α → β
x : α
⊢ (lift f) (of x) = f x

Next tactic:
convert Abelianization.lift.of
     (FreeGroup.lift f (β := Multiplicative β)) (FreeGroup.of x) using 1
@[simp]
protected theorem of (x : α) : lift f (of x) = f x := by
  convert Abelianization.lift.of
     (FreeGroup.lift f (β := Multiplicative β)) (FreeGroup.of x) using 1
  

Proof state:
case h.e'_3.h
α : Type u
β : Type v
inst✝ : AddCommGroup β
f : α → β
x : α
e_1✝ : β = Multiplicative β
⊢ f x = (FreeGroup.lift f) (FreeGroup.of x)

Next tactic:
exact (FreeGroup.lift.of (β := Multiplicative β)).symm
theorem map_hom {α β γ} [AddCommGroup β] [AddCommGroup γ] (a : FreeAbelianGroup α) (f : α → β)
    (g : β →+ γ) : g (lift f a) = lift (g ∘ f) a := by
  

Proof state:
α✝ : Type u
β✝ : Type v
inst✝² : AddCommGroup β✝
f✝ : α✝ → β✝
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : AddCommGroup β
inst✝ : AddCommGroup γ
a : FreeAbelianGroup α
f : α → β
g : β →+ γ
⊢ g ((lift f) a) = (lift (⇑g ∘ f)) a

Next tactic:
show (g.comp (lift f)) a = lift (g ∘ f) a
theorem map_hom {α β γ} [AddCommGroup β] [AddCommGroup γ] (a : FreeAbelianGroup α) (f : α → β)
    (g : β →+ γ) : g (lift f a) = lift (g ∘ f) a := by
  show (g.comp (lift f)) a = lift (g ∘ f) a
  

Proof state:
α✝ : Type u
β✝ : Type v
inst✝² : AddCommGroup β✝
f✝ : α✝ → β✝
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : AddCommGroup β
inst✝ : AddCommGroup γ
a : FreeAbelianGroup α
f : α → β
g : β →+ γ
⊢ (AddMonoidHom.comp g (lift f)) a = (lift (⇑g ∘ f)) a

Next tactic:
apply lift.unique
theorem map_hom {α β γ} [AddCommGroup β] [AddCommGroup γ] (a : FreeAbelianGroup α) (f : α → β)
    (g : β →+ γ) : g (lift f a) = lift (g ∘ f) a := by
  show (g.comp (lift f)) a = lift (g ∘ f) a
  apply lift.unique
  

Proof state:
case hg
α✝ : Type u
β✝ : Type v
inst✝² : AddCommGroup β✝
f✝ : α✝ → β✝
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : AddCommGroup β
inst✝ : AddCommGroup γ
a : FreeAbelianGroup α
f : α → β
g : β →+ γ
⊢ ∀ (x : α), (AddMonoidHom.comp g (lift f)) (of x) = (⇑g ∘ f) x

Next tactic:
intro a
theorem map_hom {α β γ} [AddCommGroup β] [AddCommGroup γ] (a : FreeAbelianGroup α) (f : α → β)
    (g : β →+ γ) : g (lift f a) = lift (g ∘ f) a := by
  show (g.comp (lift f)) a = lift (g ∘ f) a
  apply lift.unique
  intro a
  

Proof state:
case hg
α✝ : Type u
β✝ : Type v
inst✝² : AddCommGroup β✝
f✝ : α✝ → β✝
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : AddCommGroup β
inst✝ : AddCommGroup γ
a✝ : FreeAbelianGroup α
f : α → β
g : β →+ γ
a : α
⊢ (AddMonoidHom.comp g (lift f)) (of a) = (⇑g ∘ f) a

Next tactic:
show g ((lift f) (of a)) = g (f a)
theorem map_hom {α β γ} [AddCommGroup β] [AddCommGroup γ] (a : FreeAbelianGroup α) (f : α → β)
    (g : β →+ γ) : g (lift f a) = lift (g ∘ f) a := by
  show (g.comp (lift f)) a = lift (g ∘ f) a
  apply lift.unique
  intro a
  show g ((lift f) (of a)) = g (f a)
  

Proof state:
case hg
α✝ : Type u
β✝ : Type v
inst✝² : AddCommGroup β✝
f✝ : α✝ → β✝
α : Type u_1
β : Type u_2
γ : Type u_3
inst✝¹ : AddCommGroup β
inst✝ : AddCommGroup γ
a✝ : FreeAbelianGroup α
f : α → β
g : β →+ γ
a : α
⊢ g ((lift f) (of a)) = g (f a)

Next tactic:
simp only [(· ∘ ·), lift.of]
theorem lift.add' {α β} [AddCommGroup β] (a : FreeAbelianGroup α) (f g : α → β) :
    lift (f + g) a = lift f a + lift g a := by
  

Proof state:
α✝ : Type u
α : Type u_1
β : Type u_2
inst✝ : AddCommGroup β
a : FreeAbelianGroup α
f g : α → β
⊢ (lift (f + g)) a = (lift f) a + (lift g) a

Next tactic:
refine' FreeAbelianGroup.induction_on a _ _ _ _
theorem lift.add' {α β} [AddCommGroup β] (a : FreeAbelianGroup α) (f g : α → β) :
    lift (f + g) a = lift f a + lift g a := by
  refine' FreeAbelianGroup.induction_on a _ _ _ _
  · 

Proof state:
case refine'_1
α✝ : Type u
α : Type u_1
β : Type u_2
inst✝ : AddCommGroup β
a : FreeAbelianGroup α
f g : α → β
⊢ (lift (f + g)) 0 = (lift f) 0 + (lift g) 0

Next tactic:
simp only [(lift _).map_zero, zero_add]
theorem lift.add' {α β} [AddCommGroup β] (a : FreeAbelianGroup α) (f g : α → β) :
    lift (f + g) a = lift f a + lift g a := by
  refine' FreeAbelianGroup.induction_on a _ _ _ _
  · simp only [(lift _).map_zero, zero_add]
  · 

Proof state:
case refine'_2
α✝ : Type u
α : Type u_1
β : Type u_2
inst✝ : AddCommGroup β
a : FreeAbelianGroup α
f g : α → β
⊢ ∀ (x : α), (lift (f + g)) (of x) = (lift f) (of x) + (lift g) (of x)

Next tactic:
intro x
theorem lift.add' {α β} [AddCommGroup β] (a : FreeAbelianGroup α) (f g : α → β) :
    lift (f + g) a = lift f a + lift g a := by
  refine' FreeAbelianGroup.induction_on a _ _ _ _
  · simp only [(lift _).map_zero, zero_add]
  · intro x
    

Proof state:
case refine'_2
α✝ : Type u
α : Type u_1
β : Type u_2
inst✝ : AddCommGroup β
a : FreeAbelianGroup α
f g : α → β
x : α
⊢ (lift (f + g)) (of x) = (lift f) (of x) + (lift g) (of x)

Next tactic:
simp only [lift.of, Pi.add_apply]
theorem lift.add' {α β} [AddCommGroup β] (a : FreeAbelianGroup α) (f g : α → β) :
    lift (f + g) a = lift f a + lift g a := by
  refine' FreeAbelianGroup.induction_on a _ _ _ _
  · simp only [(lift _).map_zero, zero_add]
  · intro x
    simp only [lift.of, Pi.add_apply]
  · 

Proof state:
case refine'_3
α✝ : Type u
α : Type u_1
β : Type u_2
inst✝ : AddCommGroup β
a : FreeAbelianGroup α
f g : α → β
⊢ ∀ (x : α),
    (lift (f + g)) (of x) = (lift f) (of x) + (lift g) (of x) →
      (lift (f + g)) (-of x) = (lift f) (-of x) + (lift g) (-of x)

Next tactic:
intro x _
theorem lift.add' {α β} [AddCommGroup β] (a : FreeAbelianGroup α) (f g : α → β) :
    lift (f + g) a = lift f a + lift g a := by
  refine' FreeAbelianGroup.induction_on a _ _ _ _
  · simp only [(lift _).map_zero, zero_add]
  · intro x
    simp only [lift.of, Pi.add_apply]
  · intro x _
    

Proof state:
case refine'_3
α✝ : Type u
α : Type u_1
β : Type u_2
inst✝ : AddCommGroup β
a : FreeAbelianGroup α
f g : α → β
x : α
a✝ : (lift (f + g)) (of x) = (lift f) (of x) + (lift g) (of x)
⊢ (lift (f + g)) (-of x) = (lift f) (-of x) + (lift g) (-of x)

Next tactic:
simp only [map_neg, lift.of, Pi.add_apply, neg_add]
theorem lift.add' {α β} [AddCommGroup β] (a : FreeAbelianGroup α) (f g : α → β) :
    lift (f + g) a = lift f a + lift g a := by
  refine' FreeAbelianGroup.induction_on a _ _ _ _
  · simp only [(lift _).map_zero, zero_add]
  · intro x
    simp only [lift.of, Pi.add_apply]
  · intro x _
    simp only [map_neg, lift.of, Pi.add_apply, neg_add]
  · 

Proof state:
case refine'_4
α✝ : Type u
α : Type u_1
β : Type u_2
inst✝ : AddCommGroup β
a : FreeAbelianGroup α
f g : α → β
⊢ ∀ (x y : FreeAbelianGroup α),
    (lift (f + g)) x = (lift f) x + (lift g) x →
      (lift (f + g)) y = (lift f) y + (lift g) y → (lift (f + g)) (x + y) = (lift f) (x + y) + (lift g) (x + y)

Next tactic:
intro x y hx hy
theorem lift.add' {α β} [AddCommGroup β] (a : FreeAbelianGroup α) (f g : α → β) :
    lift (f + g) a = lift f a + lift g a := by
  refine' FreeAbelianGroup.induction_on a _ _ _ _
  · simp only [(lift _).map_zero, zero_add]
  · intro x
    simp only [lift.of, Pi.add_apply]
  · intro x _
    simp only [map_neg, lift.of, Pi.add_apply, neg_add]
  · intro x y hx hy
    

Proof state:
case refine'_4
α✝ : Type u
α : Type u_1
β : Type u_2
inst✝ : AddCommGroup β
a : FreeAbelianGroup α
f g : α → β
x y : FreeAbelianGroup α
hx : (lift (f + g)) x = (lift f) x + (lift g) x
hy : (lift (f + g)) y = (lift f) y + (lift g) y
⊢ (lift (f + g)) (x + y) = (lift f) (x + y) + (lift g) (x + y)

Next tactic:
simp only [(lift _).map_add, hx, hy, add_add_add_comm]
/-- If `f : FreeAbelianGroup (α → β)`, then `f <*>` is an additive morphism
`FreeAbelianGroup α →+ FreeAbelianGroup β`. -/
def seqAddGroupHom (f : FreeAbelianGroup (α → β)) : FreeAbelianGroup α →+ FreeAbelianGroup β :=
  AddMonoidHom.mk' (f <*> ·) fun x y ↦
    show lift (· <$> (x + y)) _ = _ by
      

Proof state:
α β : Type u
f : FreeAbelianGroup (α → β)
x y : FreeAbelianGroup α
⊢ (lift fun x_1 => x_1 <$> (x + y)) f = (fun x => Seq.seq f fun x_1 => x) x + (fun x => Seq.seq f fun x_1 => x) y

Next tactic:
simp only [FreeAbelianGroup.map_add]
/-- If `f : FreeAbelianGroup (α → β)`, then `f <*>` is an additive morphism
`FreeAbelianGroup α →+ FreeAbelianGroup β`. -/
def seqAddGroupHom (f : FreeAbelianGroup (α → β)) : FreeAbelianGroup α →+ FreeAbelianGroup β :=
  AddMonoidHom.mk' (f <*> ·) fun x y ↦
    show lift (· <$> (x + y)) _ = _ by
      simp only [FreeAbelianGroup.map_add]
      

Proof state:
α β : Type u
f : FreeAbelianGroup (α → β)
x y : FreeAbelianGroup α
⊢ (lift fun x_1 => x_1 <$> x + x_1 <$> y) f = (Seq.seq f fun x_1 => x) + Seq.seq f fun x => y

Next tactic:
exact lift.add' f _ _
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 

Proof state:
α β α✝ : Type u
x✝ : FreeAbelianGroup α✝
x : α✝
ih : id <$> pure x = pure x
⊢ id <$> (-pure x) = -pure x

Next tactic:
rw [FreeAbelianGroup.map_neg, ih]
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 

Proof state:
α β α✝ : Type u
x✝ x y : FreeAbelianGroup α✝
ihx : id <$> x = x
ihy : id <$> y = y
⊢ id <$> (x + y) = x + y

Next tactic:
rw [FreeAbelianGroup.map_add, 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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
⊢ 0 >>= f >>= g = 0 >>= fun x => f x >>= g

Next tactic:
iterate 3 rw [zero_bind]
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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
⊢ 0 >>= f >>= g = 0 >>= fun x => f x >>= g

Next tactic:
rw [zero_bind]
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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
⊢ 0 >>= g = 0 >>= fun x => f x >>= g

Next tactic:
rw [zero_bind]
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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
⊢ 0 = 0 >>= fun x => f x >>= g

Next tactic:
rw [zero_bind]
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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x : α✝
⊢ pure x >>= f >>= g = pure x >>= fun x => f x >>= g

Next tactic:
iterate 2 rw [pure_bind]
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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x : α✝
⊢ pure x >>= f >>= g = pure x >>= fun x => f x >>= g

Next tactic:
rw [pure_bind]
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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x : α✝
⊢ f x >>= g = pure x >>= fun x => f x >>= g

Next tactic:
rw [pure_bind]
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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x : α✝
ih : pure x >>= f >>= g = pure x >>= fun x => f x >>= g
⊢ -pure x >>= f >>= g = -pure x >>= fun x => f x >>= g

Next tactic:
iterate 3 rw [neg_bind] <;> try rw [ih]
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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x : α✝
ih : pure x >>= f >>= g = pure x >>= fun x => f x >>= g
⊢ -pure x >>= f >>= g = -pure x >>= fun x => f x >>= g

Next tactic:
rw [neg_bind]
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] <;> 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x : α✝
ih : pure x >>= f >>= g = pure x >>= fun x => f x >>= g
⊢ -(pure x >>= f) >>= g = -pure x >>= fun x => f x >>= g

Next tactic:
try rw [ih]
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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x : α✝
ih : pure x >>= f >>= g = pure x >>= fun x => f x >>= g
⊢ -(pure x >>= f) >>= g = -pure x >>= fun x => f x >>= g

Next tactic:
rw [ih]
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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x : α✝
ih : pure x >>= f >>= g = pure x >>= fun x => f x >>= g
⊢ -(pure x >>= f) >>= g = -pure x >>= fun x => f x >>= g

Next tactic:
rw [neg_bind]
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] <;> 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x : α✝
ih : pure x >>= f >>= g = pure x >>= fun x => f x >>= g
⊢ -(pure x >>= f >>= g) = -pure x >>= fun x => f x >>= g

Next tactic:
try rw [ih]
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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x : α✝
ih : pure x >>= f >>= g = pure x >>= fun x => f x >>= g
⊢ -(pure x >>= f >>= g) = -pure x >>= fun x => f x >>= g

Next tactic:
rw [ih]
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 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeAbelianGroup α✝
f : α✝ → FreeAbelianGroup β✝
g : β✝ → FreeAbelianGroup γ✝
x : α✝
ih : pure x >>= f >>= g = pure x >>= fun x => f x >>= g
⊢ -(pure x >>= fun x => f x >>= g) = -pure x >>= fun x => f x >>= g

Next tactic:
rw [neg_bind]
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 

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 + y >>= f >>= g = x + y >>= fun x => f x >>= g

Next tactic:
iterate 3 rw [add_bind] <;> 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 

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 + y >>= f >>= g = x + y >>= fun x => f x >>= g

Next tactic:
rw [add_bind]
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) + (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) + (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 >>= f) + (y >>= f) >>= g = x + y >>= fun x => f x >>= g

Next tactic:
rw [add_bind]