l3lab/ntp-mathlib huggingface dataset:
/-- The forgetful functor from `ℤ` modules to `AddCommGroup` is full. -/
instance forget₂AddCommGroupFull : Full (forget₂ (ModuleCat ℤ) AddCommGroupCat.{u}) where
  preimage {A B}
    -- `AddMonoidHom.toIntLinearMap` doesn't work here because `A` and `B` are not
    -- definitionally equal to the canonical `AddCommGroup.intModule` module
    -- instances it expects.
    f := @LinearMap.mk _ _ _ _ _ _ _ _ _ A.isModule B.isModule
        { toFun := f,
          map_add' := AddMonoidHom.map_add (show A.carrier →+ B.carrier from f) }
        (fun n x => by
          convert AddMonoidHom.map_zsmul (show A.carrier →+ B.carrier from f) x n <;>
            

Proof state:
case h.e'_3.h.e'_4.h.e'_3
A B : ModuleCat ℤ
f : (forget₂ (ModuleCat ℤ) AddCommGroupCat).obj A ⟶ (forget₂ (ModuleCat ℤ) AddCommGroupCat).obj B
n : ℤ
x : ↑A
⊢ SMulZeroClass.toSMul = SubNegMonoid.SMulInt

Next tactic:
ext
/-- The forgetful functor from `ℤ` modules to `AddCommGroup` is full. -/
instance forget₂AddCommGroupFull : Full (forget₂ (ModuleCat ℤ) AddCommGroupCat.{u}) where
  preimage {A B}
    -- `AddMonoidHom.toIntLinearMap` doesn't work here because `A` and `B` are not
    -- definitionally equal to the canonical `AddCommGroup.intModule` module
    -- instances it expects.
    f := @LinearMap.mk _ _ _ _ _ _ _ _ _ A.isModule B.isModule
        { toFun := f,
          map_add' := AddMonoidHom.map_add (show A.carrier →+ B.carrier from f) }
        (fun n x => by
          convert AddMonoidHom.map_zsmul (show A.carrier →+ B.carrier from f) x n <;>
            ext <;> 

Proof state:
case h.e'_2.h.e'_1.h.e'_4.h.e'_3.smul.h.h
A B : ModuleCat ℤ
f : (forget₂ (ModuleCat ℤ) AddCommGroupCat).obj A ⟶ (forget₂ (ModuleCat ℤ) AddCommGroupCat).obj B
n : ℤ
x : ↑A
x✝¹ : ℤ
x✝ : ↑A
⊢ SMul.smul x✝¹ x✝ = SMul.smul x✝¹ x✝

Next tactic:
apply int_smul_eq_zsmul
/-- The forgetful functor from `ℤ` modules to `AddCommGroup` is full. -/
instance forget₂AddCommGroupFull : Full (forget₂ (ModuleCat ℤ) AddCommGroupCat.{u}) where
  preimage {A B}
    -- `AddMonoidHom.toIntLinearMap` doesn't work here because `A` and `B` are not
    -- definitionally equal to the canonical `AddCommGroup.intModule` module
    -- instances it expects.
    f := @LinearMap.mk _ _ _ _ _ _ _ _ _ A.isModule B.isModule
        { toFun := f,
          map_add' := AddMonoidHom.map_add (show A.carrier →+ B.carrier from f) }
        (fun n x => by
          convert AddMonoidHom.map_zsmul (show A.carrier →+ B.carrier from f) x n <;>
            ext <;> 

Proof state:
case h.e'_3.h.e'_4.h.e'_3.smul.h.h
A B : ModuleCat ℤ
f : (forget₂ (ModuleCat ℤ) AddCommGroupCat).obj A ⟶ (forget₂ (ModuleCat ℤ) AddCommGroupCat).obj B
n : ℤ
x : ↑A
x✝¹ : ℤ
x✝ : ↑B
⊢ SMul.smul x✝¹ x✝ = SMul.smul x✝¹ x✝

Next tactic:
apply int_smul_eq_zsmul
/--
To construct an isomorphism of algebras, it suffices to give an isomorphism of the carriers which
commutes with the structure morphisms.
-/
@[simps]
def isoMk {A B : Algebra T} (h : A.A ≅ B.A)
    (w : (T : C ⥤ C).map h.hom ≫ B.a = A.a ≫ h.hom := by aesop_cat) : A ≅ B where
  hom := { f := h.hom }
  inv :=
    { f := h.inv
      h := by
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
A B : Algebra T
h : A.A ≅ B.A
w : autoParam (T.map h.hom ≫ B.a = A.a ≫ h.hom) _auto✝
⊢ T.map h.inv ≫ A.a = B.a ≫ h.inv

Next tactic:
rw [h.eq_comp_inv, Category.assoc, ← w, ← Functor.map_comp_assoc]
/--
To construct an isomorphism of algebras, it suffices to give an isomorphism of the carriers which
commutes with the structure morphisms.
-/
@[simps]
def isoMk {A B : Algebra T} (h : A.A ≅ B.A)
    (w : (T : C ⥤ C).map h.hom ≫ B.a = A.a ≫ h.hom := by aesop_cat) : A ≅ B where
  hom := { f := h.hom }
  inv :=
    { f := h.inv
      h := by
        rw [h.eq_comp_inv, Category.assoc, ← w, ← Functor.map_comp_assoc]
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
A B : Algebra T
h : A.A ≅ B.A
w : autoParam (T.map h.hom ≫ B.a = A.a ≫ h.hom) _auto✝
⊢ T.map (h.inv ≫ h.hom) ≫ B.a = B.a

Next tactic:
simp
/-- The adjunction between the free and forgetful constructions for Eilenberg-Moore algebras for
  a monad. cf Lemma 5.2.8 of [Riehl][riehl2017]. -/
@[simps! unit counit]
def adj : T.free ⊣ T.forget :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => T.η.app X ≫ f.f
          invFun := fun f =>
            { f := T.map f ≫ Y.a
              h := by
                

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
X : C
Y : Algebra T
f : X ⟶ (forget T).obj Y
⊢ T.map (T.map f ≫ Y.a) ≫ Y.a = ((free T).obj X).a ≫ T.map f ≫ Y.a

Next tactic:
dsimp
/-- The adjunction between the free and forgetful constructions for Eilenberg-Moore algebras for
  a monad. cf Lemma 5.2.8 of [Riehl][riehl2017]. -/
@[simps! unit counit]
def adj : T.free ⊣ T.forget :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => T.η.app X ≫ f.f
          invFun := fun f =>
            { f := T.map f ≫ Y.a
              h := by
                dsimp
                

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
X : C
Y : Algebra T
f : X ⟶ (forget T).obj Y
⊢ T.map (T.map f ≫ Y.a) ≫ Y.a = (μ T).app X ≫ T.map f ≫ Y.a

Next tactic:
simp [← Y.assoc, ← T.μ.naturality_assoc]
/-- The adjunction between the free and forgetful constructions for Eilenberg-Moore algebras for
  a monad. cf Lemma 5.2.8 of [Riehl][riehl2017]. -/
@[simps! unit counit]
def adj : T.free ⊣ T.forget :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => T.η.app X ≫ f.f
          invFun := fun f =>
            { f := T.map f ≫ Y.a
              h := by
                dsimp
                simp [← Y.assoc, ← T.μ.naturality_assoc] }
          left_inv := fun f => by
            

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
X : C
Y : Algebra T
f : (free T).obj X ⟶ Y
⊢ (fun f => Algebra.Hom.mk (T.map f ≫ Y.a)) ((fun f => (η T).app X ≫ f.f) f) = f

Next tactic:
ext
/-- The adjunction between the free and forgetful constructions for Eilenberg-Moore algebras for
  a monad. cf Lemma 5.2.8 of [Riehl][riehl2017]. -/
@[simps! unit counit]
def adj : T.free ⊣ T.forget :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => T.η.app X ≫ f.f
          invFun := fun f =>
            { f := T.map f ≫ Y.a
              h := by
                dsimp
                simp [← Y.assoc, ← T.μ.naturality_assoc] }
          left_inv := fun f => by
            ext
            

Proof state:
case h
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
X : C
Y : Algebra T
f : (free T).obj X ⟶ Y
⊢ ((fun f => Algebra.Hom.mk (T.map f ≫ Y.a)) ((fun f => (η T).app X ≫ f.f) f)).f = f.f

Next tactic:
dsimp
/-- The adjunction between the free and forgetful constructions for Eilenberg-Moore algebras for
  a monad. cf Lemma 5.2.8 of [Riehl][riehl2017]. -/
@[simps! unit counit]
def adj : T.free ⊣ T.forget :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => T.η.app X ≫ f.f
          invFun := fun f =>
            { f := T.map f ≫ Y.a
              h := by
                dsimp
                simp [← Y.assoc, ← T.μ.naturality_assoc] }
          left_inv := fun f => by
            ext
            dsimp
            

Proof state:
case h
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
X : C
Y : Algebra T
f : (free T).obj X ⟶ Y
⊢ T.map ((η T).app X ≫ f.f) ≫ Y.a = f.f

Next tactic:
simp
/-- The adjunction between the free and forgetful constructions for Eilenberg-Moore algebras for
  a monad. cf Lemma 5.2.8 of [Riehl][riehl2017]. -/
@[simps! unit counit]
def adj : T.free ⊣ T.forget :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => T.η.app X ≫ f.f
          invFun := fun f =>
            { f := T.map f ≫ Y.a
              h := by
                dsimp
                simp [← Y.assoc, ← T.μ.naturality_assoc] }
          left_inv := fun f => by
            ext
            dsimp
            simp
          right_inv := fun f => by
            

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
X : C
Y : Algebra T
f : X ⟶ (forget T).obj Y
⊢ (fun f => (η T).app X ≫ f.f) ((fun f => Algebra.Hom.mk (T.map f ≫ Y.a)) f) = f

Next tactic:
dsimp only [forget_obj]
/-- The adjunction between the free and forgetful constructions for Eilenberg-Moore algebras for
  a monad. cf Lemma 5.2.8 of [Riehl][riehl2017]. -/
@[simps! unit counit]
def adj : T.free ⊣ T.forget :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => T.η.app X ≫ f.f
          invFun := fun f =>
            { f := T.map f ≫ Y.a
              h := by
                dsimp
                simp [← Y.assoc, ← T.μ.naturality_assoc] }
          left_inv := fun f => by
            ext
            dsimp
            simp
          right_inv := fun f => by
            dsimp only [forget_obj]
            

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
X : C
Y : Algebra T
f : X ⟶ (forget T).obj Y
⊢ (η T).app X ≫ T.map f ≫ Y.a = f

Next tactic:
rw [← T.η.naturality_assoc, Y.unit]
/-- The adjunction between the free and forgetful constructions for Eilenberg-Moore algebras for
  a monad. cf Lemma 5.2.8 of [Riehl][riehl2017]. -/
@[simps! unit counit]
def adj : T.free ⊣ T.forget :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => T.η.app X ≫ f.f
          invFun := fun f =>
            { f := T.map f ≫ Y.a
              h := by
                dsimp
                simp [← Y.assoc, ← T.μ.naturality_assoc] }
          left_inv := fun f => by
            ext
            dsimp
            simp
          right_inv := fun f => by
            dsimp only [forget_obj]
            rw [← T.η.naturality_assoc, Y.unit]
            

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
X : C
Y : Algebra T
f : X ⟶ (forget T).obj Y
⊢ (𝟭 C).map f ≫ 𝟙 Y.A = f

Next tactic:
apply Category.comp_id
/-- The adjunction between the free and forgetful constructions for Eilenberg-Moore algebras for
  a monad. cf Lemma 5.2.8 of [Riehl][riehl2017]. -/
@[simps! unit counit]
def adj : T.free ⊣ T.forget :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => T.η.app X ≫ f.f
          invFun := fun f =>
            { f := T.map f ≫ Y.a
              h := by
                dsimp
                simp [← Y.assoc, ← T.μ.naturality_assoc] }
          left_inv := fun f => by
            ext
            dsimp
            simp
          right_inv := fun f => by
            dsimp only [forget_obj]
            rw [← T.η.naturality_assoc, Y.unit]
            apply Category.comp_id },
      -- This used to be automatic before leanprover/lean4#2644
      homEquiv_naturality_right := by
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
⊢ ∀ {X : C} {Y Y' : Algebra T} (f : (free T).obj X ⟶ Y) (g : Y ⟶ Y'),
    ((fun X Y =>
            { toFun := fun f => (η T).app X ≫ f.f, invFun := fun f => Algebra.Hom.mk (T.map f ≫ Y.a),
              left_inv :=
                (_ :
                  ∀ (f : (free T).obj X ⟶ Y),
                    (fun f => Algebra.Hom.mk (T.map f ≫ Y.a)) ((fun f => (η T).app X ≫ f.f) f) = f),
              right_inv :=
                (_ :
                  ∀ (f : X ⟶ (forget T).obj Y),
                    (fun f => (η T).app X ≫ f.f) ((fun f => Algebra.Hom.mk (T.map f ≫ Y.a)) f) = f) })
          X Y')
        (f ≫ g) =
      ((fun X Y =>
              { toFun := fun f => (η T).app X ≫ f.f, invFun := fun f => Algebra.Hom.mk (T.map f ≫ Y.a),
                left_inv :=
                  (_ :
                    ∀ (f : (free T).obj X ⟶ Y),
                      (fun f => Algebra.Hom.mk (T.map f ≫ Y.a)) ((fun f => (η T).app X ≫ f.f) f) = f),
                right_inv :=
                  (_ :
                    ∀ (f : X ⟶ (forget T).obj Y),
                      (fun f => (η T).app X ≫ f.f) ((fun f => Algebra.Hom.mk (T.map f ≫ Y.a)) f) = f) })
            X Y)
          f ≫
        (forget T).map g

Next tactic:
intros
/-- The adjunction between the free and forgetful constructions for Eilenberg-Moore algebras for
  a monad. cf Lemma 5.2.8 of [Riehl][riehl2017]. -/
@[simps! unit counit]
def adj : T.free ⊣ T.forget :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => T.η.app X ≫ f.f
          invFun := fun f =>
            { f := T.map f ≫ Y.a
              h := by
                dsimp
                simp [← Y.assoc, ← T.μ.naturality_assoc] }
          left_inv := fun f => by
            ext
            dsimp
            simp
          right_inv := fun f => by
            dsimp only [forget_obj]
            rw [← T.η.naturality_assoc, Y.unit]
            apply Category.comp_id },
      -- This used to be automatic before leanprover/lean4#2644
      homEquiv_naturality_right := by
        intros
        -- This doesn't look good:
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
X✝ : C
Y✝ Y'✝ : Algebra T
f✝ : (free T).obj X✝ ⟶ Y✝
g✝ : Y✝ ⟶ Y'✝
⊢ ((fun X Y =>
          { toFun := fun f => (η T).app X ≫ f.f, invFun := fun f => Algebra.Hom.mk (T.map f ≫ Y.a),
            left_inv :=
              (_ :
                ∀ (f : (free T).obj X ⟶ Y),
                  (fun f => Algebra.Hom.mk (T.map f ≫ Y.a)) ((fun f => (η T).app X ≫ f.f) f) = f),
            right_inv :=
              (_ :
                ∀ (f : X ⟶ (forget T).obj Y),
                  (fun f => (η T).app X ≫ f.f) ((fun f => Algebra.Hom.mk (T.map f ≫ Y.a)) f) = f) })
        X✝ Y'✝)
      (f✝ ≫ g✝) =
    ((fun X Y =>
            { toFun := fun f => (η T).app X ≫ f.f, invFun := fun f => Algebra.Hom.mk (T.map f ≫ Y.a),
              left_inv :=
                (_ :
                  ∀ (f : (free T).obj X ⟶ Y),
                    (fun f => Algebra.Hom.mk (T.map f ≫ Y.a)) ((fun f => (η T).app X ≫ f.f) f) = f),
              right_inv :=
                (_ :
                  ∀ (f : X ⟶ (forget T).obj Y),
                    (fun f => (η T).app X ≫ f.f) ((fun f => Algebra.Hom.mk (T.map f ≫ Y.a)) f) = f) })
          X✝ Y✝)
        f✝ ≫
      (forget T).map g✝

Next tactic:
simp
/-- The adjunction between the free and forgetful constructions for Eilenberg-Moore algebras for
  a monad. cf Lemma 5.2.8 of [Riehl][riehl2017]. -/
@[simps! unit counit]
def adj : T.free ⊣ T.forget :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => T.η.app X ≫ f.f
          invFun := fun f =>
            { f := T.map f ≫ Y.a
              h := by
                dsimp
                simp [← Y.assoc, ← T.μ.naturality_assoc] }
          left_inv := fun f => by
            ext
            dsimp
            simp
          right_inv := fun f => by
            dsimp only [forget_obj]
            rw [← T.η.naturality_assoc, Y.unit]
            apply Category.comp_id },
      -- This used to be automatic before leanprover/lean4#2644
      homEquiv_naturality_right := by
        intros
        -- This doesn't look good:
        simp
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
X✝ : C
Y✝ Y'✝ : Algebra T
f✝ : (free T).obj X✝ ⟶ Y✝
g✝ : Y✝ ⟶ Y'✝
⊢ { toFun := fun f => (η T).app X✝ ≫ f.f, invFun := fun f => Algebra.Hom.mk (T.map f ≫ Y'✝.a),
        left_inv := (_ : Function.LeftInverse (fun f => Algebra.Hom.mk (T.map f ≫ Y'✝.a)) fun f => (η T).app X✝ ≫ f.f),
        right_inv :=
          (_ : Function.RightInverse (fun f => Algebra.Hom.mk (T.map f ≫ Y'✝.a)) fun f => (η T).app X✝ ≫ f.f) }
      (f✝ ≫ g✝) =
    { toFun := fun f => (η T).app X✝ ≫ f.f, invFun := fun f => Algebra.Hom.mk (T.map f ≫ Y✝.a),
          left_inv := (_ : Function.LeftInverse (fun f => Algebra.Hom.mk (T.map f ≫ Y✝.a)) fun f => (η T).app X✝ ≫ f.f),
          right_inv :=
            (_ : Function.RightInverse (fun f => Algebra.Hom.mk (T.map f ≫ Y✝.a)) fun f => (η T).app X✝ ≫ f.f) }
        f✝ ≫
      g✝.f

Next tactic:
dsimp
/-- The adjunction between the free and forgetful constructions for Eilenberg-Moore algebras for
  a monad. cf Lemma 5.2.8 of [Riehl][riehl2017]. -/
@[simps! unit counit]
def adj : T.free ⊣ T.forget :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f => T.η.app X ≫ f.f
          invFun := fun f =>
            { f := T.map f ≫ Y.a
              h := by
                dsimp
                simp [← Y.assoc, ← T.μ.naturality_assoc] }
          left_inv := fun f => by
            ext
            dsimp
            simp
          right_inv := fun f => by
            dsimp only [forget_obj]
            rw [← T.η.naturality_assoc, Y.unit]
            apply Category.comp_id },
      -- This used to be automatic before leanprover/lean4#2644
      homEquiv_naturality_right := by
        intros
        -- This doesn't look good:
        simp
        dsimp
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T : Monad C
X✝ : C
Y✝ Y'✝ : Algebra T
f✝ : (free T).obj X✝ ⟶ Y✝
g✝ : Y✝ ⟶ Y'✝
⊢ (η T).app X✝ ≫ f✝.f ≫ g✝.f = ((η T).app X✝ ≫ f✝.f) ≫ g✝.f

Next tactic:
simp
/-- Given an algebra morphism whose carrier part is an isomorphism, we get an algebra isomorphism.
-/
theorem algebra_iso_of_iso {A B : Algebra T} (f : A ⟶ B) [IsIso f.f] : IsIso f :=
  ⟨⟨{   f := inv f.f
        h := by
          

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
T : Monad C
A B : Algebra T
f : A ⟶ B
inst✝ : IsIso f.f
⊢ T.map (inv f.f) ≫ A.a = B.a ≫ inv f.f

Next tactic:
rw [IsIso.eq_comp_inv f.f, Category.assoc, ← f.h]
/-- Given an algebra morphism whose carrier part is an isomorphism, we get an algebra isomorphism.
-/
theorem algebra_iso_of_iso {A B : Algebra T} (f : A ⟶ B) [IsIso f.f] : IsIso f :=
  ⟨⟨{   f := inv f.f
        h := by
          rw [IsIso.eq_comp_inv f.f, Category.assoc, ← f.h]
          

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
T : Monad C
A B : Algebra T
f : A ⟶ B
inst✝ : IsIso f.f
⊢ T.map (inv f.f) ≫ T.map f.f ≫ B.a = B.a

Next tactic:
simp
/-- Given an algebra morphism whose carrier part is an isomorphism, we get an algebra isomorphism.
-/
theorem algebra_iso_of_iso {A B : Algebra T} (f : A ⟶ B) [IsIso f.f] : IsIso f :=
  ⟨⟨{   f := inv f.f
        h := by
          rw [IsIso.eq_comp_inv f.f, Category.assoc, ← f.h]
          simp },
      by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
T : Monad C
A B : Algebra T
f : A ⟶ B
inst✝ : IsIso f.f
⊢ f ≫ Algebra.Hom.mk (inv f.f) = 𝟙 A ∧ Algebra.Hom.mk (inv f.f) ≫ f = 𝟙 B

Next tactic:
aesop_cat
/--
Given a monad morphism from `T₂` to `T₁`, we get a functor from the algebras of `T₁` to algebras of
`T₂`.
-/
@[simps]
def algebraFunctorOfMonadHom {T₁ T₂ : Monad C} (h : T₂ ⟶ T₁) : Algebra T₁ ⥤ Algebra T₂ where
  obj A :=
    { A := A.A
      a := h.app A.A ≫ A.a
      unit := by
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T T₁ T₂ : Monad C
h : T₂ ⟶ T₁
A : Algebra T₁
⊢ (η T₂).app A.A ≫ h.app A.A ≫ A.a = 𝟙 A.A

Next tactic:
dsimp
/--
Given a monad morphism from `T₂` to `T₁`, we get a functor from the algebras of `T₁` to algebras of
`T₂`.
-/
@[simps]
def algebraFunctorOfMonadHom {T₁ T₂ : Monad C} (h : T₂ ⟶ T₁) : Algebra T₁ ⥤ Algebra T₂ where
  obj A :=
    { A := A.A
      a := h.app A.A ≫ A.a
      unit := by
        dsimp
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T T₁ T₂ : Monad C
h : T₂ ⟶ T₁
A : Algebra T₁
⊢ (η T₂).app A.A ≫ h.app A.A ≫ A.a = 𝟙 A.A

Next tactic:
simp [A.unit]
/--
Given a monad morphism from `T₂` to `T₁`, we get a functor from the algebras of `T₁` to algebras of
`T₂`.
-/
@[simps]
def algebraFunctorOfMonadHom {T₁ T₂ : Monad C} (h : T₂ ⟶ T₁) : Algebra T₁ ⥤ Algebra T₂ where
  obj A :=
    { A := A.A
      a := h.app A.A ≫ A.a
      unit := by
        dsimp
        simp [A.unit]
      assoc := by
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T T₁ T₂ : Monad C
h : T₂ ⟶ T₁
A : Algebra T₁
⊢ (μ T₂).app A.A ≫ h.app A.A ≫ A.a = T₂.map (h.app A.A ≫ A.a) ≫ h.app A.A ≫ A.a

Next tactic:
dsimp
/--
Given a monad morphism from `T₂` to `T₁`, we get a functor from the algebras of `T₁` to algebras of
`T₂`.
-/
@[simps]
def algebraFunctorOfMonadHom {T₁ T₂ : Monad C} (h : T₂ ⟶ T₁) : Algebra T₁ ⥤ Algebra T₂ where
  obj A :=
    { A := A.A
      a := h.app A.A ≫ A.a
      unit := by
        dsimp
        simp [A.unit]
      assoc := by
        dsimp
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T T₁ T₂ : Monad C
h : T₂ ⟶ T₁
A : Algebra T₁
⊢ (μ T₂).app A.A ≫ h.app A.A ≫ A.a = T₂.map (h.app A.A ≫ A.a) ≫ h.app A.A ≫ A.a

Next tactic:
simp [A.assoc]
/-- Isomorphic monads give equivalent categories of algebras. Furthermore, they are equivalent as
categories over `C`, that is, we have `algebraEquivOfIsoMonads h ⋙ forget = forget`.
-/
@[simps]
def algebraEquivOfIsoMonads {T₁ T₂ : Monad C} (h : T₁ ≅ T₂) : Algebra T₁ ≌ Algebra T₂ where
  functor := algebraFunctorOfMonadHom h.inv
  inverse := algebraFunctorOfMonadHom h.hom
  unitIso :=
    algebraFunctorOfMonadHomId.symm ≪≫
      algebraFunctorOfMonadHomEq (by 

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T T₁ T₂ : Monad C
h : T₁ ≅ T₂
⊢ 𝟙 T₁ = h.hom ≫ h.inv

Next tactic:
simp
/-- Isomorphic monads give equivalent categories of algebras. Furthermore, they are equivalent as
categories over `C`, that is, we have `algebraEquivOfIsoMonads h ⋙ forget = forget`.
-/
@[simps]
def algebraEquivOfIsoMonads {T₁ T₂ : Monad C} (h : T₁ ≅ T₂) : Algebra T₁ ≌ Algebra T₂ where
  functor := algebraFunctorOfMonadHom h.inv
  inverse := algebraFunctorOfMonadHom h.hom
  unitIso :=
    algebraFunctorOfMonadHomId.symm ≪≫
      algebraFunctorOfMonadHomEq (by simp) ≪≫ algebraFunctorOfMonadHomComp _ _
  counitIso :=
    (algebraFunctorOfMonadHomComp _ _).symm ≪≫
      algebraFunctorOfMonadHomEq (by 

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
T T₁ T₂ : Monad C
h : T₁ ≅ T₂
⊢ h.inv ≫ h.hom = 𝟙 T₂

Next tactic:
simp
/--
To construct an isomorphism of coalgebras, it suffices to give an isomorphism of the carriers which
commutes with the structure morphisms.
-/
@[simps]
def isoMk {A B : Coalgebra G} (h : A.A ≅ B.A)
    (w : A.a ≫ (G : C ⥤ C).map h.hom = h.hom ≫ B.a := by aesop_cat) : A ≅ B where
  hom := { f := h.hom }
  inv :=
    { f := h.inv
      h := by
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
G : Comonad C
A B : Coalgebra G
h : A.A ≅ B.A
w : autoParam (A.a ≫ G.map h.hom = h.hom ≫ B.a) _auto✝
⊢ B.a ≫ G.map h.inv = h.inv ≫ A.a

Next tactic:
rw [h.eq_inv_comp, ← reassoc_of% w, ← Functor.map_comp]
/--
To construct an isomorphism of coalgebras, it suffices to give an isomorphism of the carriers which
commutes with the structure morphisms.
-/
@[simps]
def isoMk {A B : Coalgebra G} (h : A.A ≅ B.A)
    (w : A.a ≫ (G : C ⥤ C).map h.hom = h.hom ≫ B.a := by aesop_cat) : A ≅ B where
  hom := { f := h.hom }
  inv :=
    { f := h.inv
      h := by
        rw [h.eq_inv_comp, ← reassoc_of% w, ← Functor.map_comp]
        

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
G : Comonad C
A B : Coalgebra G
h : A.A ≅ B.A
w : autoParam (A.a ≫ G.map h.hom = h.hom ≫ B.a) _auto✝
⊢ A.a ≫ G.map (h.hom ≫ h.inv) = A.a

Next tactic:
simp
/-- The adjunction between the cofree and forgetful constructions for Eilenberg-Moore coalgebras
for a comonad.
-/
@[simps! unit counit]
def adj : G.forget ⊣ G.cofree :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f =>
            { f := X.a ≫ G.map f
              h := by
                

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
G : Comonad C
X : Coalgebra G
Y : C
f : (forget G).obj X ⟶ Y
⊢ X.a ≫ G.map (X.a ≫ G.map f) = (X.a ≫ G.map f) ≫ ((cofree G).obj Y).a

Next tactic:
dsimp
/-- The adjunction between the cofree and forgetful constructions for Eilenberg-Moore coalgebras
for a comonad.
-/
@[simps! unit counit]
def adj : G.forget ⊣ G.cofree :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        { toFun := fun f =>
            { f := X.a ≫ G.map f
              h := by
                dsimp
                

Proof state:
C : Type u₁
inst✝ : Category.{v₁, u₁} C
G : Comonad C
X : Coalgebra G
Y : C
f : (forget G).obj X ⟶ Y
⊢ X.a ≫ G.map (X.a ≫ G.map f) = (X.a ≫ G.map f) ≫ (δ G).app Y

Next tactic:
simp [← Coalgebra.coassoc_assoc]