l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
theorem lift_eq_prod_map {β : Type v} [Group β] {f : α → β} {x} : lift f x = prod (map f x) := by
  rw [← lift.unique (prod.comp (map f))]
  · rfl
  · 

Proof state:
case hg
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β : Type v
inst✝ : Group β
f : α → β
x : FreeGroup α
⊢ ∀ (x : α), (MonoidHom.comp prod (map f)) (of x) = f x

Next tactic:
simp
/-- The bijection between the free group on the empty type, and a type with one element. -/
@[to_additive "The bijection between the additive free group on the empty type, and a type with one
  element."]
def freeGroupEmptyEquivUnit : FreeGroup Empty ≃ Unit
    where
  toFun _ := ()
  invFun _ := 1
  left_inv := by 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
⊢ Function.LeftInverse (fun x => 1) fun x => ()

Next tactic:
rintro ⟨_ | ⟨⟨⟨⟩, _⟩, _⟩⟩
/-- The bijection between the free group on the empty type, and a type with one element. -/
@[to_additive "The bijection between the additive free group on the empty type, and a type with one
  element."]
def freeGroupEmptyEquivUnit : FreeGroup Empty ≃ Unit
    where
  toFun _ := ()
  invFun _ := 1
  left_inv := by rintro ⟨_ | ⟨⟨⟨⟩, _⟩, _⟩⟩; 

Proof state:
case mk.nil
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
x✝ : FreeGroup Empty
⊢ (fun x => 1) ((fun x => ()) (Quot.mk Red.Step [])) = Quot.mk Red.Step []

Next tactic:
rfl
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
x : FreeGroup Unit
⊢ FreeGroup ℤ

Next tactic:
revert x
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
⊢ FreeGroup Unit → FreeGroup ℤ

Next tactic:
change (FreeGroup Unit →* FreeGroup ℤ)
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
⊢ FreeGroup Unit →* FreeGroup ℤ

Next tactic:
apply map fun _ => (1 : ℤ)
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
⊢ Function.LeftInverse (fun x => of () ^ x) fun x =>
    sum
      ((let_fun this := map fun x => 1;
        ⇑this)
        x)

Next tactic:
rintro ⟨L⟩
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    

Proof state:
case mk
α : Type u
L✝ L₁ L₂ L₃ L₄ : List (α × Bool)
x✝ : FreeGroup Unit
L : List (Unit × Bool)
⊢ (fun x => of () ^ x)
      ((fun x =>
          sum
            ((let_fun this := map fun x => 1;
              ⇑this)
              x))
        (Quot.mk Red.Step L)) =
    Quot.mk Red.Step L

Next tactic:
simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    

Proof state:
case mk
α : Type u
L✝ L₁ L₂ L₃ L₄ : List (α × Bool)
x✝ : FreeGroup Unit
L : List (Unit × Bool)
⊢ of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) L) = mk L

Next tactic:
exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        cases b <;> simp [zpow_add] at ih ⊢ <;> rw [ih] <;> rfl)
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by 

Proof state:
α : Type u
L✝ L₁ L₂ L₃ L₄ : List (α × Bool)
x✝ : FreeGroup Unit
L : List (Unit × Bool)
⊢ of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) []) = mk []

Next tactic:
rfl
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        

Proof state:
α : Type u
L✝ L₁ L₂ L₃ L₄ : List (α × Bool)
x✝¹ : FreeGroup Unit
L : List (Unit × Bool)
x✝ : Unit × Bool
tl : List (Unit × Bool)
ih : of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) tl) = mk tl
b : Bool
⊢ of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) ((PUnit.unit, b) :: tl)) =
    mk ((PUnit.unit, b) :: tl)

Next tactic:
cases b
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        cases b <;> 

Proof state:
case false
α : Type u
L✝ L₁ L₂ L₃ L₄ : List (α × Bool)
x✝¹ : FreeGroup Unit
L : List (Unit × Bool)
x✝ : Unit × Bool
tl : List (Unit × Bool)
ih : of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) tl) = mk tl
⊢ of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) ((PUnit.unit, false) :: tl)) =
    mk ((PUnit.unit, false) :: tl)

Next tactic:
simp [zpow_add] at ih ⊢
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        cases b <;> 

Proof state:
case true
α : Type u
L✝ L₁ L₂ L₃ L₄ : List (α × Bool)
x✝¹ : FreeGroup Unit
L : List (Unit × Bool)
x✝ : Unit × Bool
tl : List (Unit × Bool)
ih : of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) tl) = mk tl
⊢ of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) ((PUnit.unit, true) :: tl)) =
    mk ((PUnit.unit, true) :: tl)

Next tactic:
simp [zpow_add] at ih ⊢
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        cases b <;> simp [zpow_add] at ih ⊢ <;> 

Proof state:
case false
α : Type u
L✝ L₁ L₂ L₃ L₄ : List (α × Bool)
x✝¹ : FreeGroup Unit
L : List (Unit × Bool)
x✝ : Unit × Bool
tl : List (Unit × Bool)
ih : of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) tl) = mk tl
⊢ (of ())⁻¹ * of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) tl) =
    mk ((PUnit.unit, false) :: tl)

Next tactic:
rw [ih]
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        cases b <;> simp [zpow_add] at ih ⊢ <;> 

Proof state:
case true
α : Type u
L✝ L₁ L₂ L₃ L₄ : List (α × Bool)
x✝¹ : FreeGroup Unit
L : List (Unit × Bool)
x✝ : Unit × Bool
tl : List (Unit × Bool)
ih : of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) tl) = mk tl
⊢ of () * of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) tl) =
    mk ((PUnit.unit, true) :: tl)

Next tactic:
rw [ih]
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        cases b <;> simp [zpow_add] at ih ⊢ <;> rw [ih] <;> 

Proof state:
case false
α : Type u
L✝ L₁ L₂ L₃ L₄ : List (α × Bool)
x✝¹ : FreeGroup Unit
L : List (Unit × Bool)
x✝ : Unit × Bool
tl : List (Unit × Bool)
ih : of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) tl) = mk tl
⊢ (of ())⁻¹ * mk tl = mk ((PUnit.unit, false) :: tl)

Next tactic:
rfl
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        cases b <;> simp [zpow_add] at ih ⊢ <;> rw [ih] <;> 

Proof state:
case true
α : Type u
L✝ L₁ L₂ L₃ L₄ : List (α × Bool)
x✝¹ : FreeGroup Unit
L : List (Unit × Bool)
x✝ : Unit × Bool
tl : List (Unit × Bool)
ih : of () ^ List.sum (List.map ((fun x => bif x.2 then x.1 else -x.1) ∘ fun x => (1, x.2)) tl) = mk tl
⊢ of () * mk tl = mk ((PUnit.unit, true) :: tl)

Next tactic:
rfl
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        cases b <;> simp [zpow_add] at ih ⊢ <;> rw [ih] <;> rfl)
  right_inv x :=
    Int.induction_on x (by 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
x : ℤ
⊢ (fun x =>
        sum
          ((let_fun this := map fun x => 1;
            ⇑this)
            x))
      ((fun x => of () ^ x) 0) =
    0

Next tactic:
simp
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        cases b <;> simp [zpow_add] at ih ⊢ <;> rw [ih] <;> rfl)
  right_inv x :=
    Int.induction_on x (by simp)
      (fun i ih => by
        

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
x : ℤ
i : ℕ
ih :
  (fun x =>
        sum
          ((let_fun this := map fun x => 1;
            ⇑this)
            x))
      ((fun x => of () ^ x) ↑i) =
    ↑i
⊢ (fun x =>
        sum
          ((let_fun this := map fun x => 1;
            ⇑this)
            x))
      ((fun x => of () ^ x) (↑i + 1)) =
    ↑i + 1

Next tactic:
simp only [zpow_coe_nat, map_pow, map.of] at ih
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        cases b <;> simp [zpow_add] at ih ⊢ <;> rw [ih] <;> rfl)
  right_inv x :=
    Int.induction_on x (by simp)
      (fun i ih => by
        simp only [zpow_coe_nat, map_pow, map.of] at ih
        

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
x : ℤ
i : ℕ
ih : sum (of 1 ^ i) = ↑i
⊢ (fun x =>
        sum
          ((let_fun this := map fun x => 1;
            ⇑this)
            x))
      ((fun x => of () ^ x) (↑i + 1)) =
    ↑i + 1

Next tactic:
simp [zpow_add, ih]
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        cases b <;> simp [zpow_add] at ih ⊢ <;> rw [ih] <;> rfl)
  right_inv x :=
    Int.induction_on x (by simp)
      (fun i ih => by
        simp only [zpow_coe_nat, map_pow, map.of] at ih
        simp [zpow_add, ih])
      (fun i ih => by
        

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
x : ℤ
i : ℕ
ih :
  (fun x =>
        sum
          ((let_fun this := map fun x => 1;
            ⇑this)
            x))
      ((fun x => of () ^ x) (-↑i)) =
    -↑i
⊢ (fun x =>
        sum
          ((let_fun this := map fun x => 1;
            ⇑this)
            x))
      ((fun x => of () ^ x) (-↑i - 1)) =
    -↑i - 1

Next tactic:
simp only [zpow_neg, zpow_coe_nat, map_inv, map_pow, map.of, sum.map_inv, neg_inj] at ih
/-- The bijection between the free group on a singleton, and the integers. -/
def freeGroupUnitEquivInt : FreeGroup Unit ≃ ℤ
    where
  toFun x := sum (by
    revert x
    change (FreeGroup Unit →* FreeGroup ℤ)
    apply map fun _ => (1 : ℤ))
  invFun x := of () ^ x
  left_inv := by
    rintro ⟨L⟩
    simp only [quot_mk_eq_mk, map.mk, sum_mk, List.map_map]
    exact List.recOn L
     (by rfl)
     (fun ⟨⟨⟩, b⟩ tl ih => by
        cases b <;> simp [zpow_add] at ih ⊢ <;> rw [ih] <;> rfl)
  right_inv x :=
    Int.induction_on x (by simp)
      (fun i ih => by
        simp only [zpow_coe_nat, map_pow, map.of] at ih
        simp [zpow_add, ih])
      (fun i ih => by
        simp only [zpow_neg, zpow_coe_nat, map_inv, map_pow, map.of, sum.map_inv, neg_inj] at ih
        

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
x : ℤ
i : ℕ
ih : sum (of 1 ^ i) = ↑i
⊢ (fun x =>
        sum
          ((let_fun this := map fun x => 1;
            ⇑this)
            x))
      ((fun x => of () ^ x) (-↑i - 1)) =
    -↑i - 1

Next tactic:
simp [zpow_add, ih, sub_eq_add_neg]
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ : Type u
x✝ : FreeGroup α✝
x : α✝
ih : id <$> pure x = pure x
⊢ id <$> (pure x)⁻¹ = (pure x)⁻¹

Next tactic:
rw [map_inv, ih]
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by rw [map_inv, ih])
      fun x y ihx ihy => by 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ : Type u
x✝ x y : FreeGroup α✝
ihx : id <$> x = x
ihy : id <$> y = y
⊢ id <$> (x * y) = x * y

Next tactic:
rw [map_mul, ihx, ihy]
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by rw [map_inv, ih])
      fun x y ihx ihy => by rw [map_mul, ihx, ihy])
  (pure_bind := fun x f => pure_bind f x)
  (bind_assoc := fun x =>
    FreeGroup.induction_on x
      (by 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ β✝ γ✝ : Type u
x : FreeGroup α✝
⊢ ∀ (f : α✝ → FreeGroup β✝) (g : β✝ → FreeGroup γ✝), 1 >>= f >>= g = 1 >>= fun x => f x >>= g

Next tactic:
intros
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by rw [map_inv, ih])
      fun x y ihx ihy => by rw [map_mul, ihx, ihy])
  (pure_bind := fun x f => pure_bind f x)
  (bind_assoc := fun x =>
    FreeGroup.induction_on x
      (by intros; 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ β✝ γ✝ : Type u
x : FreeGroup α✝
f✝ : α✝ → FreeGroup β✝
g✝ : β✝ → FreeGroup γ✝
⊢ 1 >>= f✝ >>= g✝ = 1 >>= fun x => f✝ x >>= g✝

Next tactic:
iterate 3 rw [one_bind]
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by rw [map_inv, ih])
      fun x y ihx ihy => by rw [map_mul, ihx, ihy])
  (pure_bind := fun x f => pure_bind f x)
  (bind_assoc := fun x =>
    FreeGroup.induction_on x
      (by intros; iterate 3 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ β✝ γ✝ : Type u
x : FreeGroup α✝
f✝ : α✝ → FreeGroup β✝
g✝ : β✝ → FreeGroup γ✝
⊢ 1 >>= f✝ >>= g✝ = 1 >>= fun x => f✝ x >>= g✝

Next tactic:
rw [one_bind]
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by rw [map_inv, ih])
      fun x y ihx ihy => by rw [map_mul, ihx, ihy])
  (pure_bind := fun x f => pure_bind f x)
  (bind_assoc := fun x =>
    FreeGroup.induction_on x
      (by intros; iterate 3 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ β✝ γ✝ : Type u
x : FreeGroup α✝
f✝ : α✝ → FreeGroup β✝
g✝ : β✝ → FreeGroup γ✝
⊢ 1 >>= g✝ = 1 >>= fun x => f✝ x >>= g✝

Next tactic:
rw [one_bind]
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by rw [map_inv, ih])
      fun x y ihx ihy => by rw [map_mul, ihx, ihy])
  (pure_bind := fun x f => pure_bind f x)
  (bind_assoc := fun x =>
    FreeGroup.induction_on x
      (by intros; iterate 3 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ β✝ γ✝ : Type u
x : FreeGroup α✝
f✝ : α✝ → FreeGroup β✝
g✝ : β✝ → FreeGroup γ✝
⊢ 1 = 1 >>= fun x => f✝ x >>= g✝

Next tactic:
rw [one_bind]
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by rw [map_inv, ih])
      fun x y ihx ihy => by rw [map_mul, ihx, ihy])
  (pure_bind := fun x f => pure_bind f x)
  (bind_assoc := fun x =>
    FreeGroup.induction_on x
      (by intros; iterate 3 rw [one_bind])
      (fun x => by 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ β✝ γ✝ : Type u
x✝ : FreeGroup α✝
x : α✝
⊢ ∀ (f : α✝ → FreeGroup β✝) (g : β✝ → FreeGroup γ✝), pure x >>= f >>= g = pure x >>= fun x => f x >>= g

Next tactic:
intros
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by rw [map_inv, ih])
      fun x y ihx ihy => by rw [map_mul, ihx, ihy])
  (pure_bind := fun x f => pure_bind f x)
  (bind_assoc := fun x =>
    FreeGroup.induction_on x
      (by intros; iterate 3 rw [one_bind])
      (fun x => by intros; 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ β✝ γ✝ : Type u
x✝ : FreeGroup α✝
x : α✝
f✝ : α✝ → FreeGroup β✝
g✝ : β✝ → FreeGroup γ✝
⊢ pure x >>= f✝ >>= g✝ = pure x >>= fun x => f✝ x >>= g✝

Next tactic:
iterate 2 rw [pure_bind]
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by rw [map_inv, ih])
      fun x y ihx ihy => by rw [map_mul, ihx, ihy])
  (pure_bind := fun x f => pure_bind f x)
  (bind_assoc := fun x =>
    FreeGroup.induction_on x
      (by intros; iterate 3 rw [one_bind])
      (fun x => by intros; iterate 2 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ β✝ γ✝ : Type u
x✝ : FreeGroup α✝
x : α✝
f✝ : α✝ → FreeGroup β✝
g✝ : β✝ → FreeGroup γ✝
⊢ pure x >>= f✝ >>= g✝ = pure x >>= fun x => f✝ x >>= g✝

Next tactic:
rw [pure_bind]
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by rw [map_inv, ih])
      fun x y ihx ihy => by rw [map_mul, ihx, ihy])
  (pure_bind := fun x f => pure_bind f x)
  (bind_assoc := fun x =>
    FreeGroup.induction_on x
      (by intros; iterate 3 rw [one_bind])
      (fun x => by intros; iterate 2 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ β✝ γ✝ : Type u
x✝ : FreeGroup α✝
x : α✝
f✝ : α✝ → FreeGroup β✝
g✝ : β✝ → FreeGroup γ✝
⊢ f✝ x >>= g✝ = pure x >>= fun x => f✝ x >>= g✝

Next tactic:
rw [pure_bind]
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by rw [map_inv, ih])
      fun x y ihx ihy => by rw [map_mul, ihx, ihy])
  (pure_bind := fun x f => pure_bind f x)
  (bind_assoc := fun x =>
    FreeGroup.induction_on x
      (by intros; iterate 3 rw [one_bind])
      (fun x => by intros; iterate 2 rw [pure_bind])
      (fun x ih => by 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ β✝ γ✝ : Type u
x✝ : FreeGroup α✝
x : α✝
ih : ∀ (f : α✝ → FreeGroup β✝) (g : β✝ → FreeGroup γ✝), pure x >>= f >>= g = pure x >>= fun x => f x >>= g
⊢ ∀ (f : α✝ → FreeGroup β✝) (g : β✝ → FreeGroup γ✝), (pure x)⁻¹ >>= f >>= g = (pure x)⁻¹ >>= fun x => f x >>= g

Next tactic:
intros
@[to_additive]
instance : LawfulMonad FreeGroup.{u} := LawfulMonad.mk'
  (id_map := fun x =>
    FreeGroup.induction_on x (map_one id) (fun x => map_pure id x) (fun x ih => by rw [map_inv, ih])
      fun x y ihx ihy => by rw [map_mul, ihx, ihy])
  (pure_bind := fun x f => pure_bind f x)
  (bind_assoc := fun x =>
    FreeGroup.induction_on x
      (by intros; iterate 3 rw [one_bind])
      (fun x => by intros; iterate 2 rw [pure_bind])
      (fun x ih => by intros; (

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
β α✝ β✝ γ✝ : Type u
x✝ : FreeGroup α✝
x : α✝
ih : ∀ (f : α✝ → FreeGroup β✝) (g : β✝ → FreeGroup γ✝), pure x >>= f >>= g = pure x >>= fun x => f x >>= g
f✝ : α✝ → FreeGroup β✝
g✝ : β✝ → FreeGroup γ✝
⊢ (pure x)⁻¹ >>= f✝ >>= g✝ = (pure x)⁻¹ >>= fun x => f✝ x >>= g✝

Next tactic:
iterate 3 rw [inv_bind]