l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
instance : LawfulTraversable FreeMagma.{u} :=
  { instLawfulMonad with
    id_traverse := fun x ↦
      FreeMagma.recOnPure x (fun x ↦ rfl) fun x y ih1 ih2 ↦ by
        rw [traverse_mul, ih1, ih2, mul_map_seq]
    comp_traverse := fun f g x ↦
      FreeMagma.recOnPure x
        (fun x ↦ by simp only [(· ∘ ·), traverse_pure, traverse_pure', functor_norm])
        (fun x y ih1 ih2 ↦ by
          rw [traverse_mul, ih1, ih2, traverse_mul];
          simp [Functor.Comp.map_mk, Functor.map_map, (· ∘ ·), Comp.seq_mk, seq_map_assoc,
            map_seq, traverse_mul])
    naturality := fun η α β f x ↦
      FreeMagma.recOnPure x
        (fun x ↦ by simp only [traverse_pure, functor_norm, Function.comp_apply])
        (fun x y ih1 ih2 ↦ by simp only [traverse_mul, functor_norm, ih1, ih2])
    traverse_eq_map_id := fun f x ↦
      FreeMagma.recOnPure x (fun _ ↦ rfl) fun x y ih1 ih2 ↦ by
        rw [traverse_mul, ih1, ih2, map_mul', mul_map_seq]; 

Proof state:
α β : Type u
m : Type u → Type u
inst✝ : Applicative m
F : α → m β
src✝ : LawfulMonad FreeMagma := instLawfulMonad
α✝ β✝ : Type u
f : α✝ → β✝
x✝ x y : FreeMagma α✝
ih1 : traverse (pure ∘ f) x = id.mk (f <$> x)
ih2 : traverse (pure ∘ f) y = id.mk (f <$> y)
⊢ id.mk (f <$> x) * id.mk (f <$> y) = id.mk (f <$> x * f <$> y)

Next tactic:
rfl
@[to_additive]
instance : LawfulTraversable FreeMagma.{u} :=
  { instLawfulMonad with
    id_traverse := fun x ↦
      FreeMagma.recOnPure x (fun x ↦ rfl) fun x y ih1 ih2 ↦ by
        rw [traverse_mul, ih1, ih2, mul_map_seq]
    comp_traverse := fun f g x ↦
      FreeMagma.recOnPure x
        (fun x ↦ by simp only [(· ∘ ·), traverse_pure, traverse_pure', functor_norm])
        (fun x y ih1 ih2 ↦ by
          rw [traverse_mul, ih1, ih2, traverse_mul];
          simp [Functor.Comp.map_mk, Functor.map_map, (· ∘ ·), Comp.seq_mk, seq_map_assoc,
            map_seq, traverse_mul])
    naturality := fun η α β f x ↦
      FreeMagma.recOnPure x
        (fun x ↦ by 

Proof state:
α✝ β✝ : Type u
m : Type u → Type u
inst✝⁴ : Applicative m
F : α✝ → m β✝
src✝ : LawfulMonad FreeMagma := instLawfulMonad
F✝ G✝ : Type u → Type u
inst✝³ : Applicative F✝
inst✝² : Applicative G✝
inst✝¹ : LawfulApplicative F✝
inst✝ : LawfulApplicative G✝
η : ApplicativeTransformation F✝ G✝
α β : Type u
f : α → F✝ β
x✝ : FreeMagma α
x : α
⊢ (fun {α} => ApplicativeTransformation.app η α) (traverse f (pure x)) =
    traverse ((fun {α} => ApplicativeTransformation.app η α) ∘ f) (pure x)

Next tactic:
simp only [traverse_pure, functor_norm, Function.comp_apply]
@[to_additive]
instance : LawfulTraversable FreeMagma.{u} :=
  { instLawfulMonad with
    id_traverse := fun x ↦
      FreeMagma.recOnPure x (fun x ↦ rfl) fun x y ih1 ih2 ↦ by
        rw [traverse_mul, ih1, ih2, mul_map_seq]
    comp_traverse := fun f g x ↦
      FreeMagma.recOnPure x
        (fun x ↦ by simp only [(· ∘ ·), traverse_pure, traverse_pure', functor_norm])
        (fun x y ih1 ih2 ↦ by
          rw [traverse_mul, ih1, ih2, traverse_mul];
          simp [Functor.Comp.map_mk, Functor.map_map, (· ∘ ·), Comp.seq_mk, seq_map_assoc,
            map_seq, traverse_mul])
    naturality := fun η α β f x ↦
      FreeMagma.recOnPure x
        (fun x ↦ by simp only [traverse_pure, functor_norm, Function.comp_apply])
        (fun x y ih1 ih2 ↦ by 

Proof state:
α✝ β✝ : Type u
m : Type u → Type u
inst✝⁴ : Applicative m
F : α✝ → m β✝
src✝ : LawfulMonad FreeMagma := instLawfulMonad
F✝ G✝ : Type u → Type u
inst✝³ : Applicative F✝
inst✝² : Applicative G✝
inst✝¹ : LawfulApplicative F✝
inst✝ : LawfulApplicative G✝
η : ApplicativeTransformation F✝ G✝
α β : Type u
f : α → F✝ β
x✝ x y : FreeMagma α
ih1 :
  (fun {α} => ApplicativeTransformation.app η α) (traverse f x) =
    traverse ((fun {α} => ApplicativeTransformation.app η α) ∘ f) x
ih2 :
  (fun {α} => ApplicativeTransformation.app η α) (traverse f y) =
    traverse ((fun {α} => ApplicativeTransformation.app η α) ∘ f) y
⊢ (fun {α} => ApplicativeTransformation.app η α) (traverse f (x * y)) =
    traverse ((fun {α} => ApplicativeTransformation.app η α) ∘ f) (x * y)

Next tactic:
simp only [traverse_mul, functor_norm, ih1, ih2]
@[to_additive]
instance : Semigroup (AssocQuotient α) where
  mul x y := by
    

Proof state:
α : Type u
inst✝ : Mul α
x y : AssocQuotient α
⊢ AssocQuotient α

Next tactic:
refine' Quot.liftOn₂ x y (fun x y ↦ Quot.mk _ (x * y)) _ _
@[to_additive]
instance : Semigroup (AssocQuotient α) where
  mul x y := by
    refine' Quot.liftOn₂ x y (fun x y ↦ Quot.mk _ (x * y)) _ _
    · 

Proof state:
case refine'_1
α : Type u
inst✝ : Mul α
x y : AssocQuotient α
⊢ ∀ (a b₁ b₂ : α),
    AssocRel α b₁ b₂ → (fun x y => Quot.mk (AssocRel α) (x * y)) a b₁ = (fun x y => Quot.mk (AssocRel α) (x * y)) a b₂

Next tactic:
rintro a b₁ b₂ (⟨c, d, e⟩ | ⟨c, d, e, f⟩)
@[to_additive]
instance : Semigroup (AssocQuotient α) where
  mul x y := by
    refine' Quot.liftOn₂ x y (fun x y ↦ Quot.mk _ (x * y)) _ _
    · rintro a b₁ b₂ (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> 

Proof state:
case refine'_1.intro
α : Type u
inst✝ : Mul α
x y : AssocQuotient α
a c d e : α
⊢ (fun x y => Quot.mk (AssocRel α) (x * y)) a (c * d * e) = (fun x y => Quot.mk (AssocRel α) (x * y)) a (c * (d * e))

Next tactic:
simp only
@[to_additive]
instance : Semigroup (AssocQuotient α) where
  mul x y := by
    refine' Quot.liftOn₂ x y (fun x y ↦ Quot.mk _ (x * y)) _ _
    · rintro a b₁ b₂ (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> 

Proof state:
case refine'_1.left
α : Type u
inst✝ : Mul α
x y : AssocQuotient α
a c d e f : α
⊢ (fun x y => Quot.mk (AssocRel α) (x * y)) a (c * (d * e * f)) =
    (fun x y => Quot.mk (AssocRel α) (x * y)) a (c * (d * (e * f)))

Next tactic:
simp only
@[to_additive]
instance : Semigroup (AssocQuotient α) where
  mul x y := by
    refine' Quot.liftOn₂ x y (fun x y ↦ Quot.mk _ (x * y)) _ _
    · rintro a b₁ b₂ (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> simp only
      · 

Proof state:
case refine'_1.intro
α : Type u
inst✝ : Mul α
x y : AssocQuotient α
a c d e : α
⊢ Quot.mk (AssocRel α) (a * (c * d * e)) = Quot.mk (AssocRel α) (a * (c * (d * e)))

Next tactic:
exact quot_mk_assoc_left _ _ _ _
@[to_additive]
instance : Semigroup (AssocQuotient α) where
  mul x y := by
    refine' Quot.liftOn₂ x y (fun x y ↦ Quot.mk _ (x * y)) _ _
    · rintro a b₁ b₂ (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> simp only
      · exact quot_mk_assoc_left _ _ _ _
      · 

Proof state:
case refine'_1.left
α : Type u
inst✝ : Mul α
x y : AssocQuotient α
a c d e f : α
⊢ Quot.mk (AssocRel α) (a * (c * (d * e * f))) = Quot.mk (AssocRel α) (a * (c * (d * (e * f))))

Next tactic:
rw [← quot_mk_assoc, quot_mk_assoc_left, quot_mk_assoc]
@[to_additive]
instance : Semigroup (AssocQuotient α) where
  mul x y := by
    refine' Quot.liftOn₂ x y (fun x y ↦ Quot.mk _ (x * y)) _ _
    · rintro a b₁ b₂ (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> simp only
      · exact quot_mk_assoc_left _ _ _ _
      · rw [← quot_mk_assoc, quot_mk_assoc_left, quot_mk_assoc]
    · 

Proof state:
case refine'_2
α : Type u
inst✝ : Mul α
x y : AssocQuotient α
⊢ ∀ (a₁ a₂ b : α),
    AssocRel α a₁ a₂ → (fun x y => Quot.mk (AssocRel α) (x * y)) a₁ b = (fun x y => Quot.mk (AssocRel α) (x * y)) a₂ b

Next tactic:
rintro a₁ a₂ b (⟨c, d, e⟩ | ⟨c, d, e, f⟩)
@[to_additive]
instance : Semigroup (AssocQuotient α) where
  mul x y := by
    refine' Quot.liftOn₂ x y (fun x y ↦ Quot.mk _ (x * y)) _ _
    · rintro a b₁ b₂ (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> simp only
      · exact quot_mk_assoc_left _ _ _ _
      · rw [← quot_mk_assoc, quot_mk_assoc_left, quot_mk_assoc]
    · rintro a₁ a₂ b (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> 

Proof state:
case refine'_2.intro
α : Type u
inst✝ : Mul α
x y : AssocQuotient α
b c d e : α
⊢ (fun x y => Quot.mk (AssocRel α) (x * y)) (c * d * e) b = (fun x y => Quot.mk (AssocRel α) (x * y)) (c * (d * e)) b

Next tactic:
simp only
@[to_additive]
instance : Semigroup (AssocQuotient α) where
  mul x y := by
    refine' Quot.liftOn₂ x y (fun x y ↦ Quot.mk _ (x * y)) _ _
    · rintro a b₁ b₂ (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> simp only
      · exact quot_mk_assoc_left _ _ _ _
      · rw [← quot_mk_assoc, quot_mk_assoc_left, quot_mk_assoc]
    · rintro a₁ a₂ b (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> 

Proof state:
case refine'_2.left
α : Type u
inst✝ : Mul α
x y : AssocQuotient α
b c d e f : α
⊢ (fun x y => Quot.mk (AssocRel α) (x * y)) (c * (d * e * f)) b =
    (fun x y => Quot.mk (AssocRel α) (x * y)) (c * (d * (e * f))) b

Next tactic:
simp only
@[to_additive]
instance : Semigroup (AssocQuotient α) where
  mul x y := by
    refine' Quot.liftOn₂ x y (fun x y ↦ Quot.mk _ (x * y)) _ _
    · rintro a b₁ b₂ (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> simp only
      · exact quot_mk_assoc_left _ _ _ _
      · rw [← quot_mk_assoc, quot_mk_assoc_left, quot_mk_assoc]
    · rintro a₁ a₂ b (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> simp only
      · 

Proof state:
case refine'_2.intro
α : Type u
inst✝ : Mul α
x y : AssocQuotient α
b c d e : α
⊢ Quot.mk (AssocRel α) (c * d * e * b) = Quot.mk (AssocRel α) (c * (d * e) * b)

Next tactic:
simp only [quot_mk_assoc, quot_mk_assoc_left]
@[to_additive]
instance : Semigroup (AssocQuotient α) where
  mul x y := by
    refine' Quot.liftOn₂ x y (fun x y ↦ Quot.mk _ (x * y)) _ _
    · rintro a b₁ b₂ (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> simp only
      · exact quot_mk_assoc_left _ _ _ _
      · rw [← quot_mk_assoc, quot_mk_assoc_left, quot_mk_assoc]
    · rintro a₁ a₂ b (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> simp only
      · simp only [quot_mk_assoc, quot_mk_assoc_left]
      · 

Proof state:
case refine'_2.left
α : Type u
inst✝ : Mul α
x y : AssocQuotient α
b c d e f : α
⊢ Quot.mk (AssocRel α) (c * (d * e * f) * b) = Quot.mk (AssocRel α) (c * (d * (e * f)) * b)

Next tactic:
rw [quot_mk_assoc, quot_mk_assoc, quot_mk_assoc_left, quot_mk_assoc_left,
          quot_mk_assoc_left, ← quot_mk_assoc c d, ← quot_mk_assoc c d, quot_mk_assoc_left]
/-- Lifts a magma homomorphism `α → β` to a semigroup homomorphism `Magma.AssocQuotient α → β`
given a semigroup `β`. -/
@[to_additive (attr := simps symm_apply) "Lifts an additive magma homomorphism `α → β` to an
additive semigroup homomorphism `AddMagma.AssocQuotient α → β` given an additive semigroup `β`."]
def lift : (α →ₙ* β) ≃ (AssocQuotient α →ₙ* β) where
  toFun f :=
  { toFun := fun x ↦
      Quot.liftOn x f <| by 

Proof state:
α : Type u
inst✝¹ : Mul α
β : Type v
inst✝ : Semigroup β
f✝ f : α →ₙ* β
x : AssocQuotient α
⊢ ∀ (a b : α), AssocRel α a b → f a = f b

Next tactic:
rintro a b (⟨c, d, e⟩ | ⟨c, d, e, f⟩)
/-- Lifts a magma homomorphism `α → β` to a semigroup homomorphism `Magma.AssocQuotient α → β`
given a semigroup `β`. -/
@[to_additive (attr := simps symm_apply) "Lifts an additive magma homomorphism `α → β` to an
additive semigroup homomorphism `AddMagma.AssocQuotient α → β` given an additive semigroup `β`."]
def lift : (α →ₙ* β) ≃ (AssocQuotient α →ₙ* β) where
  toFun f :=
  { toFun := fun x ↦
      Quot.liftOn x f <| by rintro a b (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> 

Proof state:
case intro
α : Type u
inst✝¹ : Mul α
β : Type v
inst✝ : Semigroup β
f✝ f : α →ₙ* β
x : AssocQuotient α
c d e : α
⊢ f (c * d * e) = f (c * (d * e))

Next tactic:
simp only [map_mul, mul_assoc]
/-- Lifts a magma homomorphism `α → β` to a semigroup homomorphism `Magma.AssocQuotient α → β`
given a semigroup `β`. -/
@[to_additive (attr := simps symm_apply) "Lifts an additive magma homomorphism `α → β` to an
additive semigroup homomorphism `AddMagma.AssocQuotient α → β` given an additive semigroup `β`."]
def lift : (α →ₙ* β) ≃ (AssocQuotient α →ₙ* β) where
  toFun f :=
  { toFun := fun x ↦
      Quot.liftOn x f <| by rintro a b (⟨c, d, e⟩ | ⟨c, d, e, f⟩) <;> 

Proof state:
case left
α : Type u
inst✝¹ : Mul α
β : Type v
inst✝ : Semigroup β
f✝¹ f✝ : α →ₙ* β
x : AssocQuotient α
c d e f : α
⊢ f✝ (c * (d * e * f)) = f✝ (c * (d * (e * f)))

Next tactic:
simp only [map_mul, mul_assoc]
@[to_additive (attr := simp)]
theorem length_mul (x y : FreeSemigroup α) : (x * y).length = x.length + y.length := by
  

Proof state:
α : Type u
x y : FreeSemigroup α
⊢ length (x * y) = length x + length y

Next tactic:
simp [length, ← add_assoc, add_right_comm, List.length, List.length_append]
@[to_additive (attr := ext 1100)]
theorem hom_ext {β : Type v} [Mul β] {f g : FreeSemigroup α →ₙ* β} (h : f ∘ of = g ∘ of) : f = g :=
  (FunLike.ext _ _) fun x ↦
    FreeSemigroup.recOnMul x (congr_fun h) fun x y hx hy ↦ by 

Proof state:
α : Type u
β : Type v
inst✝ : Mul β
f g : FreeSemigroup α →ₙ* β
h : ⇑f ∘ of = ⇑g ∘ of
x✝ : FreeSemigroup α
x : α
y : FreeSemigroup α
hx : f (of x) = g (of x)
hy : f y = g y
⊢ f (of x * y) = g (of x * y)

Next tactic:
simp only [map_mul, *]
/-- Lifts a function `α → β` to a semigroup homomorphism `FreeSemigroup α → β` given
a semigroup `β`. -/
@[to_additive (attr := simps symm_apply) "Lifts a function `α → β` to an additive semigroup
homomorphism `FreeAddSemigroup α → β` given an additive semigroup `β`."]
def lift : (α → β) ≃ (FreeSemigroup α →ₙ* β) where
  toFun f :=
    { toFun := fun x ↦ x.2.foldl (fun a b ↦ a * f b) (f x.1)
      map_mul' := fun x y ↦ by
        

Proof state:
α : Type u
β : Type v
inst✝ : Semigroup β
f✝ f : α → β
x y : FreeSemigroup α
⊢ (fun x => List.foldl (fun a b => a * f b) (f x.head) x.tail) (x * y) =
    (fun x => List.foldl (fun a b => a * f b) (f x.head) x.tail) x *
      (fun x => List.foldl (fun a b => a * f b) (f x.head) x.tail) y

Next tactic:
simp only [head_mul, tail_mul, ← List.foldl_map f, List.foldl_append, List.foldl_cons,
          List.foldl_assoc]
@[to_additive]
theorem lift_of_mul (x y) : lift f (of x * y) = f x * lift f y := by 

Proof state:
α : Type u
β : Type v
inst✝ : Semigroup β
f : α → β
x : α
y : FreeSemigroup α
⊢ (lift f) (of x * y) = f x * (lift f) y

Next tactic:
rw [map_mul, lift_of]
@[to_additive (attr := simp)]
theorem length_map (x) : (map f x).length = x.length :=
  FreeSemigroup.recOnMul x (fun x ↦ rfl) (fun x y hx hy ↦ by 

Proof state:
α : Type u
β : Type v
f : α → β
x✝ : FreeSemigroup α
x : α
y : FreeSemigroup α
hx : length ((map f) (of x)) = length (of x)
hy : length ((map f) y) = length y
⊢ length ((map f) (of x * y)) = length (of x * y)

Next tactic:
simp only [map_mul, length_mul, *]
@[to_additive]
instance instLawfulMonad : LawfulMonad FreeSemigroup.{u} := LawfulMonad.mk'
  (pure_bind := fun _ _ ↦ rfl)
  (bind_assoc := fun x g f ↦
    recOnPure x (fun x ↦ rfl) fun x y ih1 ih2 ↦ by rw [mul_bind, mul_bind, mul_bind, ih1, ih2])
  (id_map := fun x ↦ recOnPure x (fun _ ↦ rfl) fun x y ih1 ih2 ↦ by 

Proof state:
α β α✝ : Type u
x✝ : FreeSemigroup α✝
x : α✝
y : FreeSemigroup α✝
ih1 : id <$> pure x = pure x
ih2 : id <$> y = y
⊢ id <$> (pure x * y) = pure x * y

Next tactic:
rw [map_mul', ih1, ih2]
@[to_additive]
instance instLawfulMonad : LawfulMonad FreeSemigroup.{u} := LawfulMonad.mk'
  (pure_bind := fun _ _ ↦ rfl)
  (bind_assoc := fun x g f ↦
    recOnPure x (fun x ↦ rfl) fun x y ih1 ih2 ↦ by 

Proof state:
α β α✝ β✝ γ✝ : Type u
x✝ : FreeSemigroup α✝
g : α✝ → FreeSemigroup β✝
f : β✝ → FreeSemigroup γ✝
x : α✝
y : FreeSemigroup α✝
ih1 : pure x >>= g >>= f = pure x >>= fun x => g x >>= f
ih2 : y >>= g >>= f = y >>= fun x => g x >>= f
⊢ pure x * y >>= g >>= f = pure x * y >>= fun x => g x >>= f

Next tactic:
rw [mul_bind, mul_bind, mul_bind, ih1, ih2]
@[to_additive (attr := simp)]
theorem traverse_mul (x y : FreeSemigroup α) :
    traverse F (x * y) = (· * ·) <$> traverse F x <*> traverse F y :=
  let ⟨x, L1⟩ := x
  let ⟨y, L2⟩ := y
  List.recOn L1 (fun x ↦ rfl)
    (fun hd tl ih x ↦ show
        (· * ·) <$> pure <$> F x <*> traverse F (mk hd tl * mk y L2) =
          (· * ·) <$> ((· * ·) <$> pure <$> F x <*> traverse F (mk hd tl)) <*> traverse F (mk y L2)
        by 

Proof state:
α β : Type u
m : Type u → Type u
inst✝¹ : Applicative m
F : α → m β
inst✝ : LawfulApplicative m
x✝¹ y✝ : FreeSemigroup α
x✝ : α
L1 : List α
y : α
L2 : List α
hd : α
tl : List α
ih :
  ∀ (x : α),
    traverse F ({ head := x, tail := tl } * { head := y, tail := L2 }) =
      Seq.seq ((fun x x_1 => x * x_1) <$> traverse F { head := x, tail := tl }) fun x =>
        traverse F { head := y, tail := L2 }
x : α
⊢ (Seq.seq ((fun x x_1 => x * x_1) <$> pure <$> F x) fun x =>
      traverse F ({ head := hd, tail := tl } * { head := y, tail := L2 })) =
    Seq.seq
      ((fun x x_1 => x * x_1) <$>
        Seq.seq ((fun x x_1 => x * x_1) <$> pure <$> F x) fun x => traverse F { head := hd, tail := tl })
      fun x => traverse F { head := y, tail := L2 }

Next tactic:
rw [ih]
@[to_additive (attr := simp)]
theorem traverse_mul (x y : FreeSemigroup α) :
    traverse F (x * y) = (· * ·) <$> traverse F x <*> traverse F y :=
  let ⟨x, L1⟩ := x
  let ⟨y, L2⟩ := y
  List.recOn L1 (fun x ↦ rfl)
    (fun hd tl ih x ↦ show
        (· * ·) <$> pure <$> F x <*> traverse F (mk hd tl * mk y L2) =
          (· * ·) <$> ((· * ·) <$> pure <$> F x <*> traverse F (mk hd tl)) <*> traverse F (mk y L2)
        by rw [ih]; 

Proof state:
α β : Type u
m : Type u → Type u
inst✝¹ : Applicative m
F : α → m β
inst✝ : LawfulApplicative m
x✝¹ y✝ : FreeSemigroup α
x✝ : α
L1 : List α
y : α
L2 : List α
hd : α
tl : List α
ih :
  ∀ (x : α),
    traverse F ({ head := x, tail := tl } * { head := y, tail := L2 }) =
      Seq.seq ((fun x x_1 => x * x_1) <$> traverse F { head := x, tail := tl }) fun x =>
        traverse F { head := y, tail := L2 }
x : α
⊢ (Seq.seq ((fun x x_1 => x * x_1) <$> pure <$> F x) fun x =>
      Seq.seq ((fun x x_1 => x * x_1) <$> traverse F { head := hd, tail := tl }) fun x =>
        traverse F { head := y, tail := L2 }) =
    Seq.seq
      ((fun x x_1 => x * x_1) <$>
        Seq.seq ((fun x x_1 => x * x_1) <$> pure <$> F x) fun x => traverse F { head := hd, tail := tl })
      fun x => traverse F { head := y, tail := L2 }

Next tactic:
simp only [(· ∘ ·), (mul_assoc _ _ _).symm, functor_norm]
@[to_additive]
instance : LawfulTraversable FreeSemigroup.{u} :=
  { instLawfulMonad with
    id_traverse := fun x ↦
      FreeSemigroup.recOnMul x (fun x ↦ rfl) fun x y ih1 ih2 ↦ by
        

Proof state:
α β : Type u
m : Type u → Type u
inst✝ : Applicative m
F : α → m β
src✝ : LawfulMonad FreeSemigroup := instLawfulMonad
α✝ : Type u
x✝ : FreeSemigroup α✝
x : α✝
y : FreeSemigroup α✝
ih1 : traverse pure (of x) = of x
ih2 : traverse pure y = y
⊢ traverse pure (of x * y) = of x * y

Next tactic:
rw [traverse_mul, ih1, ih2, mul_map_seq]
@[to_additive]
instance : LawfulTraversable FreeSemigroup.{u} :=
  { instLawfulMonad with
    id_traverse := fun x ↦
      FreeSemigroup.recOnMul x (fun x ↦ rfl) fun x y ih1 ih2 ↦ by
        rw [traverse_mul, ih1, ih2, mul_map_seq]
    comp_traverse := fun f g x ↦
      recOnPure x (fun x ↦ by 

Proof state:
α β : Type u
m : Type u → Type u
inst✝⁴ : Applicative m
F : α → m β
src✝ : LawfulMonad FreeSemigroup := instLawfulMonad
F✝ G✝ : Type u → Type u
inst✝³ : Applicative F✝
inst✝² : Applicative G✝
inst✝¹ : LawfulApplicative F✝
inst✝ : LawfulApplicative G✝
α✝ β✝ γ✝ : Type u
f : β✝ → F✝ γ✝
g : α✝ → G✝ β✝
x✝ : FreeSemigroup α✝
x : α✝
⊢ traverse (Functor.Comp.mk ∘ Functor.map f ∘ g) (pure x) = Functor.Comp.mk (traverse f <$> traverse g (pure x))

Next tactic:
simp only [traverse_pure, functor_norm, (· ∘ ·)]
@[to_additive]
instance : LawfulTraversable FreeSemigroup.{u} :=
  { instLawfulMonad with
    id_traverse := fun x ↦
      FreeSemigroup.recOnMul x (fun x ↦ rfl) fun x y ih1 ih2 ↦ by
        rw [traverse_mul, ih1, ih2, mul_map_seq]
    comp_traverse := fun f g x ↦
      recOnPure x (fun x ↦ by simp only [traverse_pure, functor_norm, (· ∘ ·)])
        fun x y ih1 ih2 ↦ by (

Proof state:
α β : Type u
m : Type u → Type u
inst✝⁴ : Applicative m
F : α → m β
src✝ : LawfulMonad FreeSemigroup := instLawfulMonad
F✝ G✝ : Type u → Type u
inst✝³ : Applicative F✝
inst✝² : Applicative G✝
inst✝¹ : LawfulApplicative F✝
inst✝ : LawfulApplicative G✝
α✝ β✝ γ✝ : Type u
f : β✝ → F✝ γ✝
g : α✝ → G✝ β✝
x✝ : FreeSemigroup α✝
x : α✝
y : FreeSemigroup α✝
ih1 : traverse (Functor.Comp.mk ∘ Functor.map f ∘ g) (pure x) = Functor.Comp.mk (traverse f <$> traverse g (pure x))
ih2 : traverse (Functor.Comp.mk ∘ Functor.map f ∘ g) y = Functor.Comp.mk (traverse f <$> traverse g y)
⊢ traverse (Functor.Comp.mk ∘ Functor.map f ∘ g) (pure x * y) = Functor.Comp.mk (traverse f <$> traverse g (pure x * y))

Next tactic:
rw [traverse_mul, ih1, ih2,
          traverse_mul, Functor.Comp.map_mk]
@[to_additive]
instance : LawfulTraversable FreeSemigroup.{u} :=
  { instLawfulMonad with
    id_traverse := fun x ↦
      FreeSemigroup.recOnMul x (fun x ↦ rfl) fun x y ih1 ih2 ↦ by
        rw [traverse_mul, ih1, ih2, mul_map_seq]
    comp_traverse := fun f g x ↦
      recOnPure x (fun x ↦ by simp only [traverse_pure, functor_norm, (· ∘ ·)])
        fun x y ih1 ih2 ↦ by (rw [traverse_mul, ih1, ih2,
          traverse_mul, Functor.Comp.map_mk]; 

Proof state:
α β : Type u
m : Type u → Type u
inst✝⁴ : Applicative m
F : α → m β
src✝ : LawfulMonad FreeSemigroup := instLawfulMonad
F✝ G✝ : Type u → Type u
inst✝³ : Applicative F✝
inst✝² : Applicative G✝
inst✝¹ : LawfulApplicative F✝
inst✝ : LawfulApplicative G✝
α✝ β✝ γ✝ : Type u
f : β✝ → F✝ γ✝
g : α✝ → G✝ β✝
x✝ : FreeSemigroup α✝
x : α✝
y : FreeSemigroup α✝
ih1 : traverse (Functor.Comp.mk ∘ Functor.map f ∘ g) (pure x) = Functor.Comp.mk (traverse f <$> traverse g (pure x))
ih2 : traverse (Functor.Comp.mk ∘ Functor.map f ∘ g) y = Functor.Comp.mk (traverse f <$> traverse g y)
⊢ (Seq.seq (Functor.Comp.mk ((fun x => (fun x x_1 => x * x_1) <$> x) <$> traverse f <$> traverse g (pure x))) fun x =>
      Functor.Comp.mk (traverse f <$> traverse g y)) =
    Functor.Comp.mk (traverse f <$> Seq.seq ((fun x x_1 => x * x_1) <$> traverse g (pure x)) fun x => traverse g y)

Next tactic:
simp only [Function.comp, functor_norm, traverse_mul]
@[to_additive]
instance : LawfulTraversable FreeSemigroup.{u} :=
  { instLawfulMonad with
    id_traverse := fun x ↦
      FreeSemigroup.recOnMul x (fun x ↦ rfl) fun x y ih1 ih2 ↦ by
        rw [traverse_mul, ih1, ih2, mul_map_seq]
    comp_traverse := fun f g x ↦
      recOnPure x (fun x ↦ by simp only [traverse_pure, functor_norm, (· ∘ ·)])
        fun x y ih1 ih2 ↦ by (rw [traverse_mul, ih1, ih2,
          traverse_mul, Functor.Comp.map_mk]; simp only [Function.comp, functor_norm, traverse_mul])
    naturality := fun η α β f x ↦
      recOnPure x (fun x ↦ by simp only [traverse_pure, functor_norm, Function.comp])
          (fun x y ih1 ih2 ↦ by simp only [traverse_mul, functor_norm, ih1, ih2])
    traverse_eq_map_id := fun f x ↦
      FreeSemigroup.recOnMul x (fun _ ↦ rfl) fun x y ih1 ih2 ↦ by
        

Proof state:
α β : Type u
m : Type u → Type u
inst✝ : Applicative m
F : α → m β
src✝ : LawfulMonad FreeSemigroup := instLawfulMonad
α✝ β✝ : Type u
f : α✝ → β✝
x✝ : FreeSemigroup α✝
x : α✝
y : FreeSemigroup α✝
ih1 : traverse (pure ∘ f) (of x) = id.mk (f <$> of x)
ih2 : traverse (pure ∘ f) y = id.mk (f <$> y)
⊢ traverse (pure ∘ f) (of x * y) = id.mk (f <$> (of x * y))

Next tactic:
rw [traverse_mul, ih1, ih2, map_mul', mul_map_seq]
@[to_additive]
instance : LawfulTraversable FreeSemigroup.{u} :=
  { instLawfulMonad with
    id_traverse := fun x ↦
      FreeSemigroup.recOnMul x (fun x ↦ rfl) fun x y ih1 ih2 ↦ by
        rw [traverse_mul, ih1, ih2, mul_map_seq]
    comp_traverse := fun f g x ↦
      recOnPure x (fun x ↦ by simp only [traverse_pure, functor_norm, (· ∘ ·)])
        fun x y ih1 ih2 ↦ by (rw [traverse_mul, ih1, ih2,
          traverse_mul, Functor.Comp.map_mk]; simp only [Function.comp, functor_norm, traverse_mul])
    naturality := fun η α β f x ↦
      recOnPure x (fun x ↦ by simp only [traverse_pure, functor_norm, Function.comp])
          (fun x y ih1 ih2 ↦ by simp only [traverse_mul, functor_norm, ih1, ih2])
    traverse_eq_map_id := fun f x ↦
      FreeSemigroup.recOnMul x (fun _ ↦ rfl) fun x y ih1 ih2 ↦ by
        rw [traverse_mul, ih1, ih2, map_mul', mul_map_seq]; 

Proof state:
α β : Type u
m : Type u → Type u
inst✝ : Applicative m
F : α → m β
src✝ : LawfulMonad FreeSemigroup := instLawfulMonad
α✝ β✝ : Type u
f : α✝ → β✝
x✝ : FreeSemigroup α✝
x : α✝
y : FreeSemigroup α✝
ih1 : traverse (pure ∘ f) (of x) = id.mk (f <$> of x)
ih2 : traverse (pure ∘ f) y = id.mk (f <$> y)
⊢ id.mk (f <$> of x) * id.mk (f <$> y) = id.mk (f <$> of x * f <$> y)

Next tactic:
rfl