l3lab/ntp-mathlib huggingface dataset:
/-- Auxiliary definition for `FreeMonoidalCategory.project`. -/
def projectMap (X Y : F C) : (X ⟶ Y) → (projectObj f X ⟶ projectObj f Y) :=
  Quotient.lift (projectMapAux f) <| by
    intro f g h
    induction h with
    | refl => rfl
    | symm _ _ _ hfg' => exact hfg'.symm
    | trans _ _ hfg hgh => exact hfg.trans hgh
    | comp _ _ hf hg => dsimp only [projectMapAux]; rw [hf, hg]
    | tensor _ _ hfg hfg' => dsimp only [projectMapAux]; rw [hfg, hfg']
    | comp_id => dsimp only [projectMapAux]; rw [Category.comp_id]
    | id_comp => dsimp only [projectMapAux]; rw [Category.id_comp]
    | assoc => dsimp only [projectMapAux]; rw [Category.assoc]
    | tensor_id => dsimp only [projectMapAux]; rw [MonoidalCategory.tensor_id]; rfl
    | tensor_comp => dsimp only [projectMapAux]; rw [MonoidalCategory.tensor_comp]
    | α_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | α_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | associator_naturality =>
        dsimp only [projectMapAux]; rw [MonoidalCategory.associator_naturality]
    | ρ_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | ρ_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | ρ_naturality =>
        dsimp only [projectMapAux, projectObj]; rw [MonoidalCategory.rightUnitor_naturality]
    | l_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | l_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | l_naturality =>
        dsimp only [projectMapAux, projectObj]
        exact MonoidalCategory.leftUnitor_naturality _
    

Proof state:
case pentagon
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f✝ : C → D
X Y : F C
f g : X ⟶ᵐ Y
W✝ X✝ Y✝ Z✝ : F C
⊢ projectMapAux f✝
      (Hom.comp (Hom.tensor (α_hom W✝ X✝ Y✝) (Hom.id Z✝))
        (Hom.comp (α_hom W✝ (tensor X✝ Y✝) Z✝) (Hom.tensor (Hom.id W✝) (α_hom X✝ Y✝ Z✝)))) =
    projectMapAux f✝ (Hom.comp (α_hom (tensor W✝ X✝) Y✝ Z✝) (α_hom W✝ X✝ (tensor Y✝ Z✝)))

Next tactic:
| pentagon =>
        dsimp only [projectMapAux]
        exact MonoidalCategory.pentagon _ _ _ _
/-- Auxiliary definition for `FreeMonoidalCategory.project`. -/
def projectMap (X Y : F C) : (X ⟶ Y) → (projectObj f X ⟶ projectObj f Y) :=
  Quotient.lift (projectMapAux f) <| by
    intro f g h
    induction h with
    | refl => rfl
    | symm _ _ _ hfg' => exact hfg'.symm
    | trans _ _ hfg hgh => exact hfg.trans hgh
    | comp _ _ hf hg => dsimp only [projectMapAux]; rw [hf, hg]
    | tensor _ _ hfg hfg' => dsimp only [projectMapAux]; rw [hfg, hfg']
    | comp_id => dsimp only [projectMapAux]; rw [Category.comp_id]
    | id_comp => dsimp only [projectMapAux]; rw [Category.id_comp]
    | assoc => dsimp only [projectMapAux]; rw [Category.assoc]
    | tensor_id => dsimp only [projectMapAux]; rw [MonoidalCategory.tensor_id]; rfl
    | tensor_comp => dsimp only [projectMapAux]; rw [MonoidalCategory.tensor_comp]
    | α_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | α_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | associator_naturality =>
        dsimp only [projectMapAux]; rw [MonoidalCategory.associator_naturality]
    | ρ_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | ρ_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | ρ_naturality =>
        dsimp only [projectMapAux, projectObj]; rw [MonoidalCategory.rightUnitor_naturality]
    | l_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | l_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | l_naturality =>
        dsimp only [projectMapAux, projectObj]
        exact MonoidalCategory.leftUnitor_naturality _
    | pentagon =>
        

Proof state:
case pentagon
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f✝ : C → D
X Y : F C
f g : X ⟶ᵐ Y
W✝ X✝ Y✝ Z✝ : F C
⊢ projectMapAux f✝
      (Hom.comp (Hom.tensor (α_hom W✝ X✝ Y✝) (Hom.id Z✝))
        (Hom.comp (α_hom W✝ (tensor X✝ Y✝) Z✝) (Hom.tensor (Hom.id W✝) (α_hom X✝ Y✝ Z✝)))) =
    projectMapAux f✝ (Hom.comp (α_hom (tensor W✝ X✝) Y✝ Z✝) (α_hom W✝ X✝ (tensor Y✝ Z✝)))

Next tactic:
dsimp only [projectMapAux]
/-- Auxiliary definition for `FreeMonoidalCategory.project`. -/
def projectMap (X Y : F C) : (X ⟶ Y) → (projectObj f X ⟶ projectObj f Y) :=
  Quotient.lift (projectMapAux f) <| by
    intro f g h
    induction h with
    | refl => rfl
    | symm _ _ _ hfg' => exact hfg'.symm
    | trans _ _ hfg hgh => exact hfg.trans hgh
    | comp _ _ hf hg => dsimp only [projectMapAux]; rw [hf, hg]
    | tensor _ _ hfg hfg' => dsimp only [projectMapAux]; rw [hfg, hfg']
    | comp_id => dsimp only [projectMapAux]; rw [Category.comp_id]
    | id_comp => dsimp only [projectMapAux]; rw [Category.id_comp]
    | assoc => dsimp only [projectMapAux]; rw [Category.assoc]
    | tensor_id => dsimp only [projectMapAux]; rw [MonoidalCategory.tensor_id]; rfl
    | tensor_comp => dsimp only [projectMapAux]; rw [MonoidalCategory.tensor_comp]
    | α_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | α_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | associator_naturality =>
        dsimp only [projectMapAux]; rw [MonoidalCategory.associator_naturality]
    | ρ_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | ρ_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | ρ_naturality =>
        dsimp only [projectMapAux, projectObj]; rw [MonoidalCategory.rightUnitor_naturality]
    | l_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | l_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | l_naturality =>
        dsimp only [projectMapAux, projectObj]
        exact MonoidalCategory.leftUnitor_naturality _
    | pentagon =>
        dsimp only [projectMapAux]
        

Proof state:
case pentagon
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f✝ : C → D
X Y : F C
f g : X ⟶ᵐ Y
W✝ X✝ Y✝ Z✝ : F C
⊢ ((α_ (projectObj f✝ W✝) (projectObj f✝ X✝) (projectObj f✝ Y✝)).hom ⊗ 𝟙 (projectObj f✝ Z✝)) ≫
      (α_ (projectObj f✝ W✝) (projectObj f✝ (tensor X✝ Y✝)) (projectObj f✝ Z✝)).hom ≫
        (𝟙 (projectObj f✝ W✝) ⊗ (α_ (projectObj f✝ X✝) (projectObj f✝ Y✝) (projectObj f✝ Z✝)).hom) =
    (α_ (projectObj f✝ (tensor W✝ X✝)) (projectObj f✝ Y✝) (projectObj f✝ Z✝)).hom ≫
      (α_ (projectObj f✝ W✝) (projectObj f✝ X✝) (projectObj f✝ (tensor Y✝ Z✝))).hom

Next tactic:
exact MonoidalCategory.pentagon _ _ _ _
/-- Auxiliary definition for `FreeMonoidalCategory.project`. -/
def projectMap (X Y : F C) : (X ⟶ Y) → (projectObj f X ⟶ projectObj f Y) :=
  Quotient.lift (projectMapAux f) <| by
    intro f g h
    induction h with
    | refl => rfl
    | symm _ _ _ hfg' => exact hfg'.symm
    | trans _ _ hfg hgh => exact hfg.trans hgh
    | comp _ _ hf hg => dsimp only [projectMapAux]; rw [hf, hg]
    | tensor _ _ hfg hfg' => dsimp only [projectMapAux]; rw [hfg, hfg']
    | comp_id => dsimp only [projectMapAux]; rw [Category.comp_id]
    | id_comp => dsimp only [projectMapAux]; rw [Category.id_comp]
    | assoc => dsimp only [projectMapAux]; rw [Category.assoc]
    | tensor_id => dsimp only [projectMapAux]; rw [MonoidalCategory.tensor_id]; rfl
    | tensor_comp => dsimp only [projectMapAux]; rw [MonoidalCategory.tensor_comp]
    | α_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | α_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | associator_naturality =>
        dsimp only [projectMapAux]; rw [MonoidalCategory.associator_naturality]
    | ρ_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | ρ_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | ρ_naturality =>
        dsimp only [projectMapAux, projectObj]; rw [MonoidalCategory.rightUnitor_naturality]
    | l_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | l_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | l_naturality =>
        dsimp only [projectMapAux, projectObj]
        exact MonoidalCategory.leftUnitor_naturality _
    | pentagon =>
        dsimp only [projectMapAux]
        exact MonoidalCategory.pentagon _ _ _ _
    

Proof state:
case triangle
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f✝ : C → D
X Y : F C
f g : X ⟶ᵐ Y
X✝ Y✝ : F C
⊢ projectMapAux f✝ (Hom.comp (α_hom X✝ unit Y✝) (Hom.tensor (Hom.id X✝) (l_hom Y✝))) =
    projectMapAux f✝ (Hom.tensor (ρ_hom X✝) (Hom.id Y✝))

Next tactic:
| triangle =>
        dsimp only [projectMapAux]
        exact MonoidalCategory.triangle _ _
/-- Auxiliary definition for `FreeMonoidalCategory.project`. -/
def projectMap (X Y : F C) : (X ⟶ Y) → (projectObj f X ⟶ projectObj f Y) :=
  Quotient.lift (projectMapAux f) <| by
    intro f g h
    induction h with
    | refl => rfl
    | symm _ _ _ hfg' => exact hfg'.symm
    | trans _ _ hfg hgh => exact hfg.trans hgh
    | comp _ _ hf hg => dsimp only [projectMapAux]; rw [hf, hg]
    | tensor _ _ hfg hfg' => dsimp only [projectMapAux]; rw [hfg, hfg']
    | comp_id => dsimp only [projectMapAux]; rw [Category.comp_id]
    | id_comp => dsimp only [projectMapAux]; rw [Category.id_comp]
    | assoc => dsimp only [projectMapAux]; rw [Category.assoc]
    | tensor_id => dsimp only [projectMapAux]; rw [MonoidalCategory.tensor_id]; rfl
    | tensor_comp => dsimp only [projectMapAux]; rw [MonoidalCategory.tensor_comp]
    | α_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | α_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | associator_naturality =>
        dsimp only [projectMapAux]; rw [MonoidalCategory.associator_naturality]
    | ρ_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | ρ_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | ρ_naturality =>
        dsimp only [projectMapAux, projectObj]; rw [MonoidalCategory.rightUnitor_naturality]
    | l_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | l_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | l_naturality =>
        dsimp only [projectMapAux, projectObj]
        exact MonoidalCategory.leftUnitor_naturality _
    | pentagon =>
        dsimp only [projectMapAux]
        exact MonoidalCategory.pentagon _ _ _ _
    | triangle =>
        

Proof state:
case triangle
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f✝ : C → D
X Y : F C
f g : X ⟶ᵐ Y
X✝ Y✝ : F C
⊢ projectMapAux f✝ (Hom.comp (α_hom X✝ unit Y✝) (Hom.tensor (Hom.id X✝) (l_hom Y✝))) =
    projectMapAux f✝ (Hom.tensor (ρ_hom X✝) (Hom.id Y✝))

Next tactic:
dsimp only [projectMapAux]
/-- Auxiliary definition for `FreeMonoidalCategory.project`. -/
def projectMap (X Y : F C) : (X ⟶ Y) → (projectObj f X ⟶ projectObj f Y) :=
  Quotient.lift (projectMapAux f) <| by
    intro f g h
    induction h with
    | refl => rfl
    | symm _ _ _ hfg' => exact hfg'.symm
    | trans _ _ hfg hgh => exact hfg.trans hgh
    | comp _ _ hf hg => dsimp only [projectMapAux]; rw [hf, hg]
    | tensor _ _ hfg hfg' => dsimp only [projectMapAux]; rw [hfg, hfg']
    | comp_id => dsimp only [projectMapAux]; rw [Category.comp_id]
    | id_comp => dsimp only [projectMapAux]; rw [Category.id_comp]
    | assoc => dsimp only [projectMapAux]; rw [Category.assoc]
    | tensor_id => dsimp only [projectMapAux]; rw [MonoidalCategory.tensor_id]; rfl
    | tensor_comp => dsimp only [projectMapAux]; rw [MonoidalCategory.tensor_comp]
    | α_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | α_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | associator_naturality =>
        dsimp only [projectMapAux]; rw [MonoidalCategory.associator_naturality]
    | ρ_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | ρ_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | ρ_naturality =>
        dsimp only [projectMapAux, projectObj]; rw [MonoidalCategory.rightUnitor_naturality]
    | l_hom_inv => dsimp only [projectMapAux]; rw [Iso.hom_inv_id]
    | l_inv_hom => dsimp only [projectMapAux]; rw [Iso.inv_hom_id]
    | l_naturality =>
        dsimp only [projectMapAux, projectObj]
        exact MonoidalCategory.leftUnitor_naturality _
    | pentagon =>
        dsimp only [projectMapAux]
        exact MonoidalCategory.pentagon _ _ _ _
    | triangle =>
        dsimp only [projectMapAux]
        

Proof state:
case triangle
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f✝ : C → D
X Y : F C
f g : X ⟶ᵐ Y
X✝ Y✝ : F C
⊢ (α_ (projectObj f✝ X✝) (projectObj f✝ unit) (projectObj f✝ Y✝)).hom ≫
      (𝟙 (projectObj f✝ X✝) ⊗ (λ_ (projectObj f✝ Y✝)).hom) =
    (ρ_ (projectObj f✝ X✝)).hom ⊗ 𝟙 (projectObj f✝ Y✝)

Next tactic:
exact MonoidalCategory.triangle _ _
/-- If `D` is a monoidal category and we have a function `C → D`, then we have a functor from the
    free monoidal category over `C` to the category `D`. -/
def project : MonoidalFunctor (F C) D where
  obj := projectObj f
  map := projectMap f _ _
  -- Porting note: `map_comp` and `μ_natural` were proved in mathlib3 by tidy, using induction.
  -- We probably don't expect `aesop_cat` to handle this yet, see https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Aesop.20and.20cases
  -- In any case I don't understand why we need to specify `using Quotient.recOn`.
  map_comp := by 

Proof state:
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f : C → D
⊢ ∀ {X Y Z : F C} (f_1 : X ⟶ Y) (g : Y ⟶ Z),
    { obj := projectObj f, map := fun {X Y} => projectMap f X Y }.map (f_1 ≫ g) =
      { obj := projectObj f, map := fun {X Y} => projectMap f X Y }.map f_1 ≫
        { obj := projectObj f, map := fun {X Y} => projectMap f X Y }.map g

Next tactic:
rintro _ _ _ ⟨_⟩ ⟨_⟩
/-- If `D` is a monoidal category and we have a function `C → D`, then we have a functor from the
    free monoidal category over `C` to the category `D`. -/
def project : MonoidalFunctor (F C) D where
  obj := projectObj f
  map := projectMap f _ _
  -- Porting note: `map_comp` and `μ_natural` were proved in mathlib3 by tidy, using induction.
  -- We probably don't expect `aesop_cat` to handle this yet, see https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Aesop.20and.20cases
  -- In any case I don't understand why we need to specify `using Quotient.recOn`.
  map_comp := by rintro _ _ _ ⟨_⟩ ⟨_⟩; 

Proof state:
case mk.mk
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f : C → D
X✝ Y✝ Z✝ : F C
f✝ : X✝ ⟶ Y✝
a✝¹ : X✝ ⟶ᵐ Y✝
g✝ : Y✝ ⟶ Z✝
a✝ : Y✝ ⟶ᵐ Z✝
⊢ { obj := projectObj f, map := fun {X Y} => projectMap f X Y }.map (Quot.mk Setoid.r a✝¹ ≫ Quot.mk Setoid.r a✝) =
    { obj := projectObj f, map := fun {X Y} => projectMap f X Y }.map (Quot.mk Setoid.r a✝¹) ≫
      { obj := projectObj f, map := fun {X Y} => projectMap f X Y }.map (Quot.mk Setoid.r a✝)

Next tactic:
rfl
/-- If `D` is a monoidal category and we have a function `C → D`, then we have a functor from the
    free monoidal category over `C` to the category `D`. -/
def project : MonoidalFunctor (F C) D where
  obj := projectObj f
  map := projectMap f _ _
  -- Porting note: `map_comp` and `μ_natural` were proved in mathlib3 by tidy, using induction.
  -- We probably don't expect `aesop_cat` to handle this yet, see https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Aesop.20and.20cases
  -- In any case I don't understand why we need to specify `using Quotient.recOn`.
  map_comp := by rintro _ _ _ ⟨_⟩ ⟨_⟩; rfl
  ε := 𝟙 _
  μ X Y := 𝟙 _
  μ_natural := @fun _ _ _ _ f g => by
    

Proof state:
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f✝ : C → D
x✝³ x✝² x✝¹ x✝ : F C
f : x✝³ ⟶ x✝²
g : x✝¹ ⟶ x✝
⊢ ((Functor.mk { obj := projectObj f✝, map := fun {X Y} => projectMap f✝ X Y }).map f ⊗
        (Functor.mk { obj := projectObj f✝, map := fun {X Y} => projectMap f✝ X Y }).map g) ≫
      (fun X Y =>
          𝟙
            ((Functor.mk { obj := projectObj f✝, map := fun {X Y} => projectMap f✝ X Y }).obj X ⊗
              (Functor.mk { obj := projectObj f✝, map := fun {X Y} => projectMap f✝ X Y }).obj Y))
        x✝² x✝ =
    (fun X Y =>
          𝟙
            ((Functor.mk { obj := projectObj f✝, map := fun {X Y} => projectMap f✝ X Y }).obj X ⊗
              (Functor.mk { obj := projectObj f✝, map := fun {X Y} => projectMap f✝ X Y }).obj Y))
        x✝³ x✝¹ ≫
      (Functor.mk { obj := projectObj f✝, map := fun {X Y} => projectMap f✝ X Y }).map (f ⊗ g)

Next tactic:
induction' f using Quotient.recOn
/-- If `D` is a monoidal category and we have a function `C → D`, then we have a functor from the
    free monoidal category over `C` to the category `D`. -/
def project : MonoidalFunctor (F C) D where
  obj := projectObj f
  map := projectMap f _ _
  -- Porting note: `map_comp` and `μ_natural` were proved in mathlib3 by tidy, using induction.
  -- We probably don't expect `aesop_cat` to handle this yet, see https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Aesop.20and.20cases
  -- In any case I don't understand why we need to specify `using Quotient.recOn`.
  map_comp := by rintro _ _ _ ⟨_⟩ ⟨_⟩; rfl
  ε := 𝟙 _
  μ X Y := 𝟙 _
  μ_natural := @fun _ _ _ _ f g => by
    induction' f using Quotient.recOn
    · 

Proof state:
case f
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f : C → D
x✝³ x✝² x✝¹ x✝ : F C
g : x✝¹ ⟶ x✝
a✝ : x✝³ ⟶ᵐ x✝²
⊢ ((Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).map ⟦a✝⟧ ⊗
        (Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).map g) ≫
      (fun X Y =>
          𝟙
            ((Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).obj X ⊗
              (Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).obj Y))
        x✝² x✝ =
    (fun X Y =>
          𝟙
            ((Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).obj X ⊗
              (Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).obj Y))
        x✝³ x✝¹ ≫
      (Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).map (⟦a✝⟧ ⊗ g)

Next tactic:
induction' g using Quotient.recOn
/-- If `D` is a monoidal category and we have a function `C → D`, then we have a functor from the
    free monoidal category over `C` to the category `D`. -/
def project : MonoidalFunctor (F C) D where
  obj := projectObj f
  map := projectMap f _ _
  -- Porting note: `map_comp` and `μ_natural` were proved in mathlib3 by tidy, using induction.
  -- We probably don't expect `aesop_cat` to handle this yet, see https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Aesop.20and.20cases
  -- In any case I don't understand why we need to specify `using Quotient.recOn`.
  map_comp := by rintro _ _ _ ⟨_⟩ ⟨_⟩; rfl
  ε := 𝟙 _
  μ X Y := 𝟙 _
  μ_natural := @fun _ _ _ _ f g => by
    induction' f using Quotient.recOn
    · induction' g using Quotient.recOn
      · 

Proof state:
case f.f
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f : C → D
x✝³ x✝² x✝¹ x✝ : F C
a✝¹ : x✝³ ⟶ᵐ x✝²
a✝ : x✝¹ ⟶ᵐ x✝
⊢ ((Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).map ⟦a✝¹⟧ ⊗
        (Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).map ⟦a✝⟧) ≫
      (fun X Y =>
          𝟙
            ((Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).obj X ⊗
              (Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).obj Y))
        x✝² x✝ =
    (fun X Y =>
          𝟙
            ((Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).obj X ⊗
              (Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).obj Y))
        x✝³ x✝¹ ≫
      (Functor.mk { obj := projectObj f, map := fun {X Y} => projectMap f X Y }).map (⟦a✝¹⟧ ⊗ ⟦a✝⟧)

Next tactic:
dsimp
/-- If `D` is a monoidal category and we have a function `C → D`, then we have a functor from the
    free monoidal category over `C` to the category `D`. -/
def project : MonoidalFunctor (F C) D where
  obj := projectObj f
  map := projectMap f _ _
  -- Porting note: `map_comp` and `μ_natural` were proved in mathlib3 by tidy, using induction.
  -- We probably don't expect `aesop_cat` to handle this yet, see https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Aesop.20and.20cases
  -- In any case I don't understand why we need to specify `using Quotient.recOn`.
  map_comp := by rintro _ _ _ ⟨_⟩ ⟨_⟩; rfl
  ε := 𝟙 _
  μ X Y := 𝟙 _
  μ_natural := @fun _ _ _ _ f g => by
    induction' f using Quotient.recOn
    · induction' g using Quotient.recOn
      · dsimp
        

Proof state:
case f.f
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f : C → D
x✝³ x✝² x✝¹ x✝ : F C
a✝¹ : x✝³ ⟶ᵐ x✝²
a✝ : x✝¹ ⟶ᵐ x✝
⊢ (projectMap f x✝³ x✝² ⟦a✝¹⟧ ⊗ projectMap f x✝¹ x✝ ⟦a✝⟧) ≫ 𝟙 (projectObj f x✝² ⊗ projectObj f x✝) =
    𝟙 (projectObj f x✝³ ⊗ projectObj f x✝¹) ≫ projectMap f (x✝³ ⊗ x✝¹) (x✝² ⊗ x✝) (⟦a✝¹⟧ ⊗ ⟦a✝⟧)

Next tactic:
simp
/-- If `D` is a monoidal category and we have a function `C → D`, then we have a functor from the
    free monoidal category over `C` to the category `D`. -/
def project : MonoidalFunctor (F C) D where
  obj := projectObj f
  map := projectMap f _ _
  -- Porting note: `map_comp` and `μ_natural` were proved in mathlib3 by tidy, using induction.
  -- We probably don't expect `aesop_cat` to handle this yet, see https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Aesop.20and.20cases
  -- In any case I don't understand why we need to specify `using Quotient.recOn`.
  map_comp := by rintro _ _ _ ⟨_⟩ ⟨_⟩; rfl
  ε := 𝟙 _
  μ X Y := 𝟙 _
  μ_natural := @fun _ _ _ _ f g => by
    induction' f using Quotient.recOn
    · induction' g using Quotient.recOn
      · dsimp
        simp
        

Proof state:
case f.f
C : Type u
D : Type u'
inst✝¹ : Category.{v', u'} D
inst✝ : MonoidalCategory D
f : C → D
x✝³ x✝² x✝¹ x✝ : F C
a✝¹ : x✝³ ⟶ᵐ x✝²
a✝ : x✝¹ ⟶ᵐ x✝
⊢ projectMap f x✝³ x✝² ⟦a✝¹⟧ ⊗ projectMap f x✝¹ x✝ ⟦a✝⟧ = projectMap f (x✝³ ⊗ x✝¹) (x✝² ⊗ x✝) (⟦a✝¹⟧ ⊗ ⟦a✝⟧)

Next tactic:
rfl