/-
Copyright (c) 2019 Reid Barton. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Reid Barton, Johan Commelin

! This file was ported from Lean 3 source module category_theory.adjunction.limits
! leanprover-community/mathlib commit f47581155c818e6361af4e4fda60d27d020c226b
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.CategoryTheory.Adjunction.Basic
import Mathbin.CategoryTheory.Limits.Creates

/-!
# Adjunctions and limits

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

A left adjoint preserves colimits (`category_theory.adjunction.left_adjoint_preserves_colimits`),
and a right adjoint preserves limits (`category_theory.adjunction.right_adjoint_preserves_limits`).

Equivalences create and reflect (co)limits.
(`category_theory.adjunction.is_equivalence_creates_limits`,
`category_theory.adjunction.is_equivalence_creates_colimits`,
`category_theory.adjunction.is_equivalence_reflects_limits`,
`category_theory.adjunction.is_equivalence_reflects_colimits`,)

In `category_theory.adjunction.cocones_iso` we show that
when `F ⊣ G`,
the functor associating to each `Y` the cocones over `K ⋙ F` with cone point `Y`
is naturally isomorphic to
the functor associating to each `Y` the cocones over `K` with cone point `G.obj Y`.
-/

open Opposite

namespace CategoryTheory.Adjunction

open CategoryTheory

open CategoryTheory.Functor

open CategoryTheory.Limits

universe v u v₁ v₂ v₀ u₁ u₂

section ArbitraryUniverse

variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D]

variable {F : C ⥤ D} {G : D ⥤ C} (adj : F ⊣ G)

include adj

section PreservationColimits

variable {J : Type u} [Category.{v} J] (K : J ⥤ C)

#print CategoryTheory.Adjunction.functorialityRightAdjoint /-
/-- The right adjoint of `cocones.functoriality K F : cocone K ⥤ cocone (K ⋙ F)`.

Auxiliary definition for `functoriality_is_left_adjoint`.
-/
def functorialityRightAdjoint : Cocone (K ⋙ F) ⥤ Cocone K :=
  Cocones.functoriality _ G ⋙
    Cocones.precompose (K.rightUnitor.inv ≫ whiskerLeft K adj.Unit ≫ (associator _ _ _).inv)
#align category_theory.adjunction.functoriality_right_adjoint CategoryTheory.Adjunction.functorialityRightAdjoint
-/

attribute [local reducible] functoriality_right_adjoint

#print CategoryTheory.Adjunction.functorialityUnit /-
/-- The unit for the adjunction for `cocones.functoriality K F : cocone K ⥤ cocone (K ⋙ F)`.

Auxiliary definition for `functoriality_is_left_adjoint`.
-/
@[simps]
def functorialityUnit : 𝟭 (Cocone K) ⟶ Cocones.functoriality _ F ⋙ functorialityRightAdjoint adj K
    where app c := { Hom := adj.Unit.app c.pt }
#align category_theory.adjunction.functoriality_unit CategoryTheory.Adjunction.functorialityUnit
-/

#print CategoryTheory.Adjunction.functorialityCounit /-
/-- The counit for the adjunction for `cocones.functoriality K F : cocone K ⥤ cocone (K ⋙ F)`.

Auxiliary definition for `functoriality_is_left_adjoint`.
-/
@[simps]
def functorialityCounit :
    functorialityRightAdjoint adj K ⋙ Cocones.functoriality _ F ⟶ 𝟭 (Cocone (K ⋙ F))
    where app c := { Hom := adj.counit.app c.pt }
#align category_theory.adjunction.functoriality_counit CategoryTheory.Adjunction.functorialityCounit
-/

#print CategoryTheory.Adjunction.functorialityIsLeftAdjoint /-
/-- The functor `cocones.functoriality K F : cocone K ⥤ cocone (K ⋙ F)` is a left adjoint. -/
def functorialityIsLeftAdjoint : IsLeftAdjoint (Cocones.functoriality K F)
    where
  right := functorialityRightAdjoint adj K
  adj :=
    mkOfUnitCounit
      { Unit := functorialityUnit adj K
        counit := functorialityCounit adj K }
#align category_theory.adjunction.functoriality_is_left_adjoint CategoryTheory.Adjunction.functorialityIsLeftAdjoint
-/

#print CategoryTheory.Adjunction.leftAdjointPreservesColimits /-
/-- A left adjoint preserves colimits.

See <https://stacks.math.columbia.edu/tag/0038>.
-/
def leftAdjointPreservesColimits : PreservesColimitsOfSize.{v, u} F
    where PreservesColimitsOfShape J 𝒥 :=
    {
      PreservesColimit := fun F =>
        {
          preserves := fun c hc =>
            is_colimit.iso_unique_cocone_morphism.inv fun s =>
              @Equiv.unique _ _ (is_colimit.iso_unique_cocone_morphism.hom hc _)
                ((adj.functoriality_is_left_adjoint _).adj.homEquiv _ _) } }
#align category_theory.adjunction.left_adjoint_preserves_colimits CategoryTheory.Adjunction.leftAdjointPreservesColimits
-/

omit adj

#print CategoryTheory.Adjunction.isEquivalencePreservesColimits /-
-- see Note [lower instance priority]
instance (priority := 100) isEquivalencePreservesColimits (E : C ⥤ D) [IsEquivalence E] :
    PreservesColimitsOfSize.{v, u} E :=
  leftAdjointPreservesColimits E.Adjunction
#align category_theory.adjunction.is_equivalence_preserves_colimits CategoryTheory.Adjunction.isEquivalencePreservesColimits
-/

#print CategoryTheory.Adjunction.isEquivalenceReflectsColimits /-
-- see Note [lower instance priority]
instance (priority := 100) isEquivalenceReflectsColimits (E : D ⥤ C) [IsEquivalence E] :
    ReflectsColimitsOfSize.{v, u} E
    where ReflectsColimitsOfShape J 𝒥 :=
    {
      ReflectsColimit := fun K =>
        {
          reflects := fun c t =>
            by
            have l :=
              (is_colimit_of_preserves E.inv t).mapCoconeEquiv E.as_equivalence.unit_iso.symm
            refine' ((is_colimit.precompose_inv_equiv K.right_unitor _).symm l).ofIsoColimit _
            tidy } }
#align category_theory.adjunction.is_equivalence_reflects_colimits CategoryTheory.Adjunction.isEquivalenceReflectsColimits
-/

#print CategoryTheory.Adjunction.isEquivalenceCreatesColimits /-
-- see Note [lower instance priority]
instance (priority := 100) isEquivalenceCreatesColimits (H : D ⥤ C) [IsEquivalence H] :
    CreatesColimitsOfSize.{v, u} H
    where CreatesColimitsOfShape J 𝒥 :=
    {
      CreatesColimit := fun F =>
        {
          lifts := fun c t =>
            { liftedCocone := H.map_cocone_inv c
              validLift := H.map_cocone_map_cocone_inv c } } }
#align category_theory.adjunction.is_equivalence_creates_colimits CategoryTheory.Adjunction.isEquivalenceCreatesColimits
-/

-- verify the preserve_colimits instance works as expected:
example (E : C ⥤ D) [IsEquivalence E] (c : Cocone K) (h : IsColimit c) :
    IsColimit (E.mapCocone c) :=
  PreservesColimit.preserves h

#print CategoryTheory.Adjunction.hasColimit_comp_equivalence /-
theorem hasColimit_comp_equivalence (E : C ⥤ D) [IsEquivalence E] [HasColimit K] :
    HasColimit (K ⋙ E) :=
  HasColimit.mk
    { Cocone := E.mapCocone (colimit.cocone K)
      IsColimit := PreservesColimit.preserves (colimit.isColimit K) }
#align category_theory.adjunction.has_colimit_comp_equivalence CategoryTheory.Adjunction.hasColimit_comp_equivalence
-/

#print CategoryTheory.Adjunction.hasColimit_of_comp_equivalence /-
theorem hasColimit_of_comp_equivalence (E : C ⥤ D) [IsEquivalence E] [HasColimit (K ⋙ E)] :
    HasColimit K :=
  @hasColimitOfIso _ _ _ _ (K ⋙ E ⋙ inv E) K
    (@hasColimit_comp_equivalence _ _ _ _ _ _ (K ⋙ E) (inv E) _ _)
    ((Functor.rightUnitor _).symm ≪≫ isoWhiskerLeft K E.asEquivalence.unitIso)
#align category_theory.adjunction.has_colimit_of_comp_equivalence CategoryTheory.Adjunction.hasColimit_of_comp_equivalence
-/

#print CategoryTheory.Adjunction.hasColimitsOfShape_of_equivalence /-
/-- Transport a `has_colimits_of_shape` instance across an equivalence. -/
theorem hasColimitsOfShape_of_equivalence (E : C ⥤ D) [IsEquivalence E] [HasColimitsOfShape J D] :
    HasColimitsOfShape J C :=
  ⟨fun F => has_colimit_of_comp_equivalence F E⟩
#align category_theory.adjunction.has_colimits_of_shape_of_equivalence CategoryTheory.Adjunction.hasColimitsOfShape_of_equivalence
-/

#print CategoryTheory.Adjunction.has_colimits_of_equivalence /-
/-- Transport a `has_colimits` instance across an equivalence. -/
theorem has_colimits_of_equivalence (E : C ⥤ D) [IsEquivalence E] [HasColimitsOfSize.{v, u} D] :
    HasColimitsOfSize.{v, u} C :=
  ⟨fun J hJ => has_colimits_of_shape_of_equivalence E⟩
#align category_theory.adjunction.has_colimits_of_equivalence CategoryTheory.Adjunction.has_colimits_of_equivalence
-/

end PreservationColimits

section PreservationLimits

variable {J : Type u} [Category.{v} J] (K : J ⥤ D)

#print CategoryTheory.Adjunction.functorialityLeftAdjoint /-
/-- The left adjoint of `cones.functoriality K G : cone K ⥤ cone (K ⋙ G)`.

Auxiliary definition for `functoriality_is_right_adjoint`.
-/
def functorialityLeftAdjoint : Cone (K ⋙ G) ⥤ Cone K :=
  Cones.functoriality _ F ⋙
    Cones.postcompose ((associator _ _ _).Hom ≫ whiskerLeft K adj.counit ≫ K.rightUnitor.Hom)
#align category_theory.adjunction.functoriality_left_adjoint CategoryTheory.Adjunction.functorialityLeftAdjoint
-/

attribute [local reducible] functoriality_left_adjoint

#print CategoryTheory.Adjunction.functorialityUnit' /-
/-- The unit for the adjunction for`cones.functoriality K G : cone K ⥤ cone (K ⋙ G)`.

Auxiliary definition for `functoriality_is_right_adjoint`.
-/
@[simps]
def functorialityUnit' : 𝟭 (Cone (K ⋙ G)) ⟶ functorialityLeftAdjoint adj K ⋙ Cones.functoriality _ G
    where app c := { Hom := adj.Unit.app c.pt }
#align category_theory.adjunction.functoriality_unit' CategoryTheory.Adjunction.functorialityUnit'
-/

#print CategoryTheory.Adjunction.functorialityCounit' /-
/-- The counit for the adjunction for`cones.functoriality K G : cone K ⥤ cone (K ⋙ G)`.

Auxiliary definition for `functoriality_is_right_adjoint`.
-/
@[simps]
def functorialityCounit' : Cones.functoriality _ G ⋙ functorialityLeftAdjoint adj K ⟶ 𝟭 (Cone K)
    where app c := { Hom := adj.counit.app c.pt }
#align category_theory.adjunction.functoriality_counit' CategoryTheory.Adjunction.functorialityCounit'
-/

#print CategoryTheory.Adjunction.functorialityIsRightAdjoint /-
/-- The functor `cones.functoriality K G : cone K ⥤ cone (K ⋙ G)` is a right adjoint. -/
def functorialityIsRightAdjoint : IsRightAdjoint (Cones.functoriality K G)
    where
  left := functorialityLeftAdjoint adj K
  adj :=
    mkOfUnitCounit
      { Unit := functorialityUnit' adj K
        counit := functorialityCounit' adj K }
#align category_theory.adjunction.functoriality_is_right_adjoint CategoryTheory.Adjunction.functorialityIsRightAdjoint
-/

#print CategoryTheory.Adjunction.rightAdjointPreservesLimits /-
/-- A right adjoint preserves limits.

See <https://stacks.math.columbia.edu/tag/0038>.
-/
def rightAdjointPreservesLimits : PreservesLimitsOfSize.{v, u} G
    where PreservesLimitsOfShape J 𝒥 :=
    {
      PreservesLimit := fun K =>
        {
          preserves := fun c hc =>
            is_limit.iso_unique_cone_morphism.inv fun s =>
              @Equiv.unique _ _ (is_limit.iso_unique_cone_morphism.hom hc _)
                ((adj.functoriality_is_right_adjoint _).adj.homEquiv _ _).symm } }
#align category_theory.adjunction.right_adjoint_preserves_limits CategoryTheory.Adjunction.rightAdjointPreservesLimits
-/

omit adj

#print CategoryTheory.Adjunction.isEquivalencePreservesLimits /-
-- see Note [lower instance priority]
instance (priority := 100) isEquivalencePreservesLimits (E : D ⥤ C) [IsEquivalence E] :
    PreservesLimitsOfSize.{v, u} E :=
  rightAdjointPreservesLimits E.inv.Adjunction
#align category_theory.adjunction.is_equivalence_preserves_limits CategoryTheory.Adjunction.isEquivalencePreservesLimits
-/

#print CategoryTheory.Adjunction.isEquivalenceReflectsLimits /-
-- see Note [lower instance priority]
instance (priority := 100) isEquivalenceReflectsLimits (E : D ⥤ C) [IsEquivalence E] :
    ReflectsLimitsOfSize.{v, u} E
    where ReflectsLimitsOfShape J 𝒥 :=
    {
      ReflectsLimit := fun K =>
        {
          reflects := fun c t =>
            by
            have := (is_limit_of_preserves E.inv t).mapConeEquiv E.as_equivalence.unit_iso.symm
            refine' ((is_limit.postcompose_hom_equiv K.left_unitor _).symm this).ofIsoLimit _
            tidy } }
#align category_theory.adjunction.is_equivalence_reflects_limits CategoryTheory.Adjunction.isEquivalenceReflectsLimits
-/

#print CategoryTheory.Adjunction.isEquivalenceCreatesLimits /-
-- see Note [lower instance priority]
instance (priority := 100) isEquivalenceCreatesLimits (H : D ⥤ C) [IsEquivalence H] :
    CreatesLimitsOfSize.{v, u} H
    where CreatesLimitsOfShape J 𝒥 :=
    {
      CreatesLimit := fun F =>
        {
          lifts := fun c t =>
            { liftedCone := H.map_cone_inv c
              validLift := H.map_cone_map_cone_inv c } } }
#align category_theory.adjunction.is_equivalence_creates_limits CategoryTheory.Adjunction.isEquivalenceCreatesLimits
-/

-- verify the preserve_limits instance works as expected:
example (E : D ⥤ C) [IsEquivalence E] (c : Cone K) [h : IsLimit c] : IsLimit (E.mapCone c) :=
  PreservesLimit.preserves h

#print CategoryTheory.Adjunction.hasLimit_comp_equivalence /-
theorem hasLimit_comp_equivalence (E : D ⥤ C) [IsEquivalence E] [HasLimit K] : HasLimit (K ⋙ E) :=
  HasLimit.mk
    { Cone := E.mapCone (limit.cone K)
      IsLimit := PreservesLimit.preserves (limit.isLimit K) }
#align category_theory.adjunction.has_limit_comp_equivalence CategoryTheory.Adjunction.hasLimit_comp_equivalence
-/

#print CategoryTheory.Adjunction.hasLimit_of_comp_equivalence /-
theorem hasLimit_of_comp_equivalence (E : D ⥤ C) [IsEquivalence E] [HasLimit (K ⋙ E)] :
    HasLimit K :=
  @hasLimitOfIso _ _ _ _ (K ⋙ E ⋙ inv E) K
    (@hasLimit_comp_equivalence _ _ _ _ _ _ (K ⋙ E) (inv E) _ _)
    (isoWhiskerLeft K E.asEquivalence.unitIso.symm ≪≫ Functor.rightUnitor _)
#align category_theory.adjunction.has_limit_of_comp_equivalence CategoryTheory.Adjunction.hasLimit_of_comp_equivalence
-/

#print CategoryTheory.Adjunction.hasLimitsOfShape_of_equivalence /-
/-- Transport a `has_limits_of_shape` instance across an equivalence. -/
theorem hasLimitsOfShape_of_equivalence (E : D ⥤ C) [IsEquivalence E] [HasLimitsOfShape J C] :
    HasLimitsOfShape J D :=
  ⟨fun F => has_limit_of_comp_equivalence F E⟩
#align category_theory.adjunction.has_limits_of_shape_of_equivalence CategoryTheory.Adjunction.hasLimitsOfShape_of_equivalence
-/

#print CategoryTheory.Adjunction.has_limits_of_equivalence /-
/-- Transport a `has_limits` instance across an equivalence. -/
theorem has_limits_of_equivalence (E : D ⥤ C) [IsEquivalence E] [HasLimitsOfSize.{v, u} C] :
    HasLimitsOfSize.{v, u} D :=
  ⟨fun J hJ => has_limits_of_shape_of_equivalence E⟩
#align category_theory.adjunction.has_limits_of_equivalence CategoryTheory.Adjunction.has_limits_of_equivalence
-/

end PreservationLimits

/- warning: category_theory.adjunction.cocones_iso_component_hom -> CategoryTheory.Adjunction.coconesIsoComponentHom is a dubious translation:
lean 3 declaration is
  forall {C : Type.{u5}} [_inst_1 : CategoryTheory.Category.{u3, u5} C] {D : Type.{u6}} [_inst_2 : CategoryTheory.Category.{u4, u6} D] {F : CategoryTheory.Functor.{u3, u4, u5, u6} C _inst_1 D _inst_2} {G : CategoryTheory.Functor.{u4, u3, u6, u5} D _inst_2 C _inst_1}, (CategoryTheory.Adjunction.{u3, u4, u5, u6} C _inst_1 D _inst_2 F G) -> (forall {J : Type.{u2}} [_inst_3 : CategoryTheory.Category.{u1, u2} J] {K : CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1} (Y : D), (CategoryTheory.Functor.obj.{u4, max u2 u4, u6, succ (max u2 u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4} (CategoryTheory.Functor.obj.{max u2 u4, max u6 u2 u4, max u1 u4 u2 u6, max u4 (max u2 u4) u6 (succ (max u2 u4))} (Opposite.{succ (max u1 u4 u2 u6)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.Category.opposite.{max u2 u4, max u1 u4 u2 u6} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.Functor.{u4, max u2 u4, u6, succ (max u2 u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Functor.category.{u4, max u2 u4, u6, succ (max u2 u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.cocones.{u1, u4, u2, u6} J _inst_3 D _inst_2) (Opposite.op.{succ (max u1 u4 u2 u6)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.comp.{u1, u3, u4, u2, u5, u6} J _inst_3 C _inst_1 D _inst_2 K F))) Y) -> (CategoryTheory.Functor.obj.{u4, max u2 u3, u6, succ (max u2 u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3} (CategoryTheory.Functor.comp.{u4, u3, max u2 u3, u6, u5, succ (max u2 u3)} D _inst_2 C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3} G (CategoryTheory.Functor.obj.{max u2 u3, max u5 u2 u3, max u1 u3 u2 u5, max u3 (max u2 u3) u5 (succ (max u2 u3))} (Opposite.{succ (max u1 u3 u2 u5)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Category.opposite.{max u2 u3, max u1 u3 u2 u5} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Functor.{u3, max u2 u3, u5, succ (max u2 u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, succ (max u2 u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cocones.{u1, u3, u2, u5} J _inst_3 C _inst_1) (Opposite.op.{succ (max u1 u3 u2 u5)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) K))) Y))
but is expected to have type
  forall {C : Type.{u5}} [_inst_1 : CategoryTheory.Category.{u3, u5} C] {D : Type.{u6}} [_inst_2 : CategoryTheory.Category.{u4, u6} D] {F : CategoryTheory.Functor.{u3, u4, u5, u6} C _inst_1 D _inst_2} {G : CategoryTheory.Functor.{u4, u3, u6, u5} D _inst_2 C _inst_1}, (CategoryTheory.Adjunction.{u3, u4, u5, u6} C _inst_1 D _inst_2 F G) -> (forall {J : Type.{u2}} [_inst_3 : CategoryTheory.Category.{u1, u2} J] {K : CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1} (Y : D), (Prefunctor.obj.{succ u4, max (succ u2) (succ u4), u6, max (succ u2) (succ u4)} D (CategoryTheory.CategoryStruct.toQuiver.{u4, u6} D (CategoryTheory.Category.toCategoryStruct.{u4, u6} D _inst_2)) Type.{max u2 u4} (CategoryTheory.CategoryStruct.toQuiver.{max u2 u4, max (succ u2) (succ u4)} Type.{max u2 u4} (CategoryTheory.Category.toCategoryStruct.{max u2 u4, max (succ u2) (succ u4)} Type.{max u2 u4} CategoryTheory.types.{max u2 u4})) (CategoryTheory.Functor.toPrefunctor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4} (Prefunctor.obj.{max (succ u2) (succ u4), max (max (succ u2) (succ u6)) (succ u4), max (max (max u2 u6) u1) u4, max (max (succ u2) u6) (succ u4)} (Opposite.{succ (max (max (max u6 u2) u4) u1)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.CategoryStruct.toQuiver.{max u2 u4, max (max (max u2 u6) u1) u4} (Opposite.{succ (max (max (max u6 u2) u4) u1)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.Category.toCategoryStruct.{max u2 u4, max (max (max u2 u6) u1) u4} (Opposite.{succ (max (max (max u6 u2) u4) u1)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.Category.opposite.{max u2 u4, max (max (max u2 u6) u1) u4} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u4, u2, u6} J _inst_3 D _inst_2)))) (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.CategoryStruct.toQuiver.{max (max u2 u6) u4, max (max (succ u2) u6) (succ u4)} (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Category.toCategoryStruct.{max (max u2 u6) u4, max (max (succ u2) u6) (succ u4)} (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Functor.category.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}))) (CategoryTheory.Functor.toPrefunctor.{max u2 u4, max (max u2 u6) u4, max (max (max u2 u6) u1) u4, max (max (succ u2) u6) (succ u4)} (Opposite.{succ (max (max (max u6 u2) u4) u1)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.Category.opposite.{max u2 u4, max (max (max u2 u6) u1) u4} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Functor.category.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.cocones.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (Opposite.op.{max (max (max (succ u2) (succ u6)) (succ u1)) (succ u4)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.comp.{u1, u3, u4, u2, u5, u6} J _inst_3 C _inst_1 D _inst_2 K F)))) Y) -> (Prefunctor.obj.{succ u4, max (succ u2) (succ u3), u6, max (succ u2) (succ u3)} D (CategoryTheory.CategoryStruct.toQuiver.{u4, u6} D (CategoryTheory.Category.toCategoryStruct.{u4, u6} D _inst_2)) Type.{max u2 u3} (CategoryTheory.CategoryStruct.toQuiver.{max u2 u3, max (succ u2) (succ u3)} Type.{max u2 u3} (CategoryTheory.Category.toCategoryStruct.{max u2 u3, max (succ u2) (succ u3)} Type.{max u2 u3} CategoryTheory.types.{max u2 u3})) (CategoryTheory.Functor.toPrefunctor.{u4, max u2 u3, u6, max (succ u2) (succ u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3} (CategoryTheory.Functor.comp.{u4, u3, max u2 u3, u6, u5, max (succ u2) (succ u3)} D _inst_2 C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3} G (Prefunctor.obj.{max (succ u2) (succ u3), max (max (succ u2) (succ u5)) (succ u3), max (max (max u2 u5) u1) u3, max (max (succ u2) u5) (succ u3)} (Opposite.{succ (max (max (max u5 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.CategoryStruct.toQuiver.{max u2 u3, max (max (max u2 u5) u1) u3} (Opposite.{succ (max (max (max u5 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Category.toCategoryStruct.{max u2 u3, max (max (max u2 u5) u1) u3} (Opposite.{succ (max (max (max u5 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Category.opposite.{max u2 u3, max (max (max u2 u5) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 C _inst_1)))) (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.CategoryStruct.toQuiver.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Category.toCategoryStruct.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}))) (CategoryTheory.Functor.toPrefunctor.{max u2 u3, max (max u2 u5) u3, max (max (max u2 u5) u1) u3, max (max (succ u2) u5) (succ u3)} (Opposite.{succ (max (max (max u5 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Category.opposite.{max u2 u3, max (max (max u2 u5) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cocones.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (Opposite.op.{max (max (max (succ u2) (succ u5)) (succ u1)) (succ u3)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) K)))) Y))
Case conversion may be inaccurate. Consider using '#align category_theory.adjunction.cocones_iso_component_hom CategoryTheory.Adjunction.coconesIsoComponentHomₓ'. -/
/-- auxiliary construction for `cocones_iso` -/
@[simps]
def coconesIsoComponentHom {J : Type u} [Category.{v} J] {K : J ⥤ C} (Y : D)
    (t : ((cocones J D).obj (op (K ⋙ F))).obj Y) : (G ⋙ (cocones J C).obj (op K)).obj Y
    where
  app j := (adj.homEquiv (K.obj j) Y) (t.app j)
  naturality' j j' f := by
    erw [← adj.hom_equiv_naturality_left, t.naturality]
    dsimp
    simp
#align category_theory.adjunction.cocones_iso_component_hom CategoryTheory.Adjunction.coconesIsoComponentHom

/- warning: category_theory.adjunction.cocones_iso_component_inv -> CategoryTheory.Adjunction.coconesIsoComponentInv is a dubious translation:
lean 3 declaration is
  forall {C : Type.{u5}} [_inst_1 : CategoryTheory.Category.{u3, u5} C] {D : Type.{u6}} [_inst_2 : CategoryTheory.Category.{u4, u6} D] {F : CategoryTheory.Functor.{u3, u4, u5, u6} C _inst_1 D _inst_2} {G : CategoryTheory.Functor.{u4, u3, u6, u5} D _inst_2 C _inst_1}, (CategoryTheory.Adjunction.{u3, u4, u5, u6} C _inst_1 D _inst_2 F G) -> (forall {J : Type.{u2}} [_inst_3 : CategoryTheory.Category.{u1, u2} J] {K : CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1} (Y : D), (CategoryTheory.Functor.obj.{u4, max u2 u3, u6, succ (max u2 u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3} (CategoryTheory.Functor.comp.{u4, u3, max u2 u3, u6, u5, succ (max u2 u3)} D _inst_2 C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3} G (CategoryTheory.Functor.obj.{max u2 u3, max u5 u2 u3, max u1 u3 u2 u5, max u3 (max u2 u3) u5 (succ (max u2 u3))} (Opposite.{succ (max u1 u3 u2 u5)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Category.opposite.{max u2 u3, max u1 u3 u2 u5} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Functor.{u3, max u2 u3, u5, succ (max u2 u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, succ (max u2 u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cocones.{u1, u3, u2, u5} J _inst_3 C _inst_1) (Opposite.op.{succ (max u1 u3 u2 u5)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) K))) Y) -> (CategoryTheory.Functor.obj.{u4, max u2 u4, u6, succ (max u2 u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4} (CategoryTheory.Functor.obj.{max u2 u4, max u6 u2 u4, max u1 u4 u2 u6, max u4 (max u2 u4) u6 (succ (max u2 u4))} (Opposite.{succ (max u1 u4 u2 u6)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.Category.opposite.{max u2 u4, max u1 u4 u2 u6} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.Functor.{u4, max u2 u4, u6, succ (max u2 u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Functor.category.{u4, max u2 u4, u6, succ (max u2 u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.cocones.{u1, u4, u2, u6} J _inst_3 D _inst_2) (Opposite.op.{succ (max u1 u4 u2 u6)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.comp.{u1, u3, u4, u2, u5, u6} J _inst_3 C _inst_1 D _inst_2 K F))) Y))
but is expected to have type
  forall {C : Type.{u5}} [_inst_1 : CategoryTheory.Category.{u3, u5} C] {D : Type.{u6}} [_inst_2 : CategoryTheory.Category.{u4, u6} D] {F : CategoryTheory.Functor.{u3, u4, u5, u6} C _inst_1 D _inst_2} {G : CategoryTheory.Functor.{u4, u3, u6, u5} D _inst_2 C _inst_1}, (CategoryTheory.Adjunction.{u3, u4, u5, u6} C _inst_1 D _inst_2 F G) -> (forall {J : Type.{u2}} [_inst_3 : CategoryTheory.Category.{u1, u2} J] {K : CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1} (Y : D), (Prefunctor.obj.{succ u4, max (succ u2) (succ u3), u6, max (succ u2) (succ u3)} D (CategoryTheory.CategoryStruct.toQuiver.{u4, u6} D (CategoryTheory.Category.toCategoryStruct.{u4, u6} D _inst_2)) Type.{max u2 u3} (CategoryTheory.CategoryStruct.toQuiver.{max u2 u3, max (succ u2) (succ u3)} Type.{max u2 u3} (CategoryTheory.Category.toCategoryStruct.{max u2 u3, max (succ u2) (succ u3)} Type.{max u2 u3} CategoryTheory.types.{max u2 u3})) (CategoryTheory.Functor.toPrefunctor.{u4, max u2 u3, u6, max (succ u2) (succ u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3} (CategoryTheory.Functor.comp.{u4, u3, max u2 u3, u6, u5, max (succ u2) (succ u3)} D _inst_2 C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3} G (Prefunctor.obj.{max (succ u2) (succ u3), max (max (succ u2) (succ u5)) (succ u3), max (max (max u2 u5) u1) u3, max (max (succ u2) u5) (succ u3)} (Opposite.{succ (max (max (max u5 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.CategoryStruct.toQuiver.{max u2 u3, max (max (max u2 u5) u1) u3} (Opposite.{succ (max (max (max u5 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Category.toCategoryStruct.{max u2 u3, max (max (max u2 u5) u1) u3} (Opposite.{succ (max (max (max u5 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Category.opposite.{max u2 u3, max (max (max u2 u5) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 C _inst_1)))) (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.CategoryStruct.toQuiver.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Category.toCategoryStruct.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}))) (CategoryTheory.Functor.toPrefunctor.{max u2 u3, max (max u2 u5) u3, max (max (max u2 u5) u1) u3, max (max (succ u2) u5) (succ u3)} (Opposite.{succ (max (max (max u5 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Category.opposite.{max u2 u3, max (max (max u2 u5) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cocones.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (Opposite.op.{max (max (max (succ u2) (succ u5)) (succ u1)) (succ u3)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) K)))) Y) -> (Prefunctor.obj.{succ u4, max (succ u2) (succ u4), u6, max (succ u2) (succ u4)} D (CategoryTheory.CategoryStruct.toQuiver.{u4, u6} D (CategoryTheory.Category.toCategoryStruct.{u4, u6} D _inst_2)) Type.{max u2 u4} (CategoryTheory.CategoryStruct.toQuiver.{max u2 u4, max (succ u2) (succ u4)} Type.{max u2 u4} (CategoryTheory.Category.toCategoryStruct.{max u2 u4, max (succ u2) (succ u4)} Type.{max u2 u4} CategoryTheory.types.{max u2 u4})) (CategoryTheory.Functor.toPrefunctor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4} (Prefunctor.obj.{max (succ u2) (succ u4), max (max (succ u2) (succ u6)) (succ u4), max (max (max u2 u6) u1) u4, max (max (succ u2) u6) (succ u4)} (Opposite.{succ (max (max (max u6 u2) u4) u1)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.CategoryStruct.toQuiver.{max u2 u4, max (max (max u2 u6) u1) u4} (Opposite.{succ (max (max (max u6 u2) u4) u1)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.Category.toCategoryStruct.{max u2 u4, max (max (max u2 u6) u1) u4} (Opposite.{succ (max (max (max u6 u2) u4) u1)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.Category.opposite.{max u2 u4, max (max (max u2 u6) u1) u4} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u4, u2, u6} J _inst_3 D _inst_2)))) (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.CategoryStruct.toQuiver.{max (max u2 u6) u4, max (max (succ u2) u6) (succ u4)} (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Category.toCategoryStruct.{max (max u2 u6) u4, max (max (succ u2) u6) (succ u4)} (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Functor.category.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}))) (CategoryTheory.Functor.toPrefunctor.{max u2 u4, max (max u2 u6) u4, max (max (max u2 u6) u1) u4, max (max (succ u2) u6) (succ u4)} (Opposite.{succ (max (max (max u6 u2) u4) u1)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.Category.opposite.{max u2 u4, max (max (max u2 u6) u1) u4} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Functor.category.{u4, max u2 u4, u6, max (succ u2) (succ u4)} D _inst_2 Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.cocones.{u1, u4, u2, u6} J _inst_3 D _inst_2)) (Opposite.op.{max (max (max (succ u2) (succ u6)) (succ u1)) (succ u4)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.comp.{u1, u3, u4, u2, u5, u6} J _inst_3 C _inst_1 D _inst_2 K F)))) Y))
Case conversion may be inaccurate. Consider using '#align category_theory.adjunction.cocones_iso_component_inv CategoryTheory.Adjunction.coconesIsoComponentInvₓ'. -/
/-- auxiliary construction for `cocones_iso` -/
@[simps]
def coconesIsoComponentInv {J : Type u} [Category.{v} J] {K : J ⥤ C} (Y : D)
    (t : (G ⋙ (cocones J C).obj (op K)).obj Y) : ((cocones J D).obj (op (K ⋙ F))).obj Y
    where
  app j := (adj.homEquiv (K.obj j) Y).symm (t.app j)
  naturality' j j' f :=
    by
    erw [← adj.hom_equiv_naturality_left_symm, ← adj.hom_equiv_naturality_right_symm, t.naturality]
    dsimp; simp
#align category_theory.adjunction.cocones_iso_component_inv CategoryTheory.Adjunction.coconesIsoComponentInv

/- warning: category_theory.adjunction.cones_iso_component_hom -> CategoryTheory.Adjunction.conesIsoComponentHom is a dubious translation:
lean 3 declaration is
  forall {C : Type.{u5}} [_inst_1 : CategoryTheory.Category.{u3, u5} C] {D : Type.{u6}} [_inst_2 : CategoryTheory.Category.{u4, u6} D] {F : CategoryTheory.Functor.{u3, u4, u5, u6} C _inst_1 D _inst_2} {G : CategoryTheory.Functor.{u4, u3, u6, u5} D _inst_2 C _inst_1}, (CategoryTheory.Adjunction.{u3, u4, u5, u6} C _inst_1 D _inst_2 F G) -> (forall {J : Type.{u2}} [_inst_3 : CategoryTheory.Category.{u1, u2} J] {K : CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2} (X : Opposite.{succ u5} C), (CategoryTheory.Functor.obj.{u3, max u2 u4, u5, succ (max u2 u4)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u4} CategoryTheory.types.{max u2 u4} (CategoryTheory.Functor.comp.{u3, u4, max u2 u4, u5, u6, succ (max u2 u4)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4} (CategoryTheory.Functor.op.{u3, u4, u5, u6} C _inst_1 D _inst_2 F) (CategoryTheory.Functor.obj.{max u2 u4, max u6 u2 u4, max u1 u4 u2 u6, max u4 (max u2 u4) u6 (succ (max u2 u4))} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.{u4, max u2 u4, u6, succ (max u2 u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Functor.category.{u4, max u2 u4, u6, succ (max u2 u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.cones.{u1, u4, u2, u6} J _inst_3 D _inst_2) K)) X) -> (CategoryTheory.Functor.obj.{u3, max u2 u3, u5, succ (max u2 u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3} (CategoryTheory.Functor.obj.{max u2 u3, max u5 u2 u3, max u1 u3 u2 u5, max u3 (max u2 u3) u5 (succ (max u2 u3))} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.{u3, max u2 u3, u5, succ (max u2 u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, succ (max u2 u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cones.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.comp.{u1, u4, u3, u2, u6, u5} J _inst_3 D _inst_2 C _inst_1 K G)) X))
but is expected to have type
  forall {C : Type.{u5}} [_inst_1 : CategoryTheory.Category.{u3, u5} C] {D : Type.{u6}} [_inst_2 : CategoryTheory.Category.{u4, u6} D] {F : CategoryTheory.Functor.{u3, u4, u5, u6} C _inst_1 D _inst_2} {G : CategoryTheory.Functor.{u4, u3, u6, u5} D _inst_2 C _inst_1}, (CategoryTheory.Adjunction.{u3, u4, u5, u6} C _inst_1 D _inst_2 F G) -> (forall {J : Type.{u2}} [_inst_3 : CategoryTheory.Category.{u1, u2} J] {K : CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2} (X : Opposite.{succ u5} C), (Prefunctor.obj.{succ u3, max (succ u2) (succ u4), u5, max (succ u2) (succ u4)} (Opposite.{succ u5} C) (CategoryTheory.CategoryStruct.toQuiver.{u3, u5} (Opposite.{succ u5} C) (CategoryTheory.Category.toCategoryStruct.{u3, u5} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1))) Type.{max u2 u4} (CategoryTheory.CategoryStruct.toQuiver.{max u2 u4, max (succ u2) (succ u4)} Type.{max u2 u4} (CategoryTheory.Category.toCategoryStruct.{max u2 u4, max (succ u2) (succ u4)} Type.{max u2 u4} CategoryTheory.types.{max u2 u4})) (CategoryTheory.Functor.toPrefunctor.{u3, max u2 u4, u5, max (succ u2) (succ u4)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u4} CategoryTheory.types.{max u2 u4} (CategoryTheory.Functor.comp.{u3, u4, max u2 u4, u5, u6, max (succ u2) (succ u4)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4} (CategoryTheory.Functor.op.{u3, u4, u5, u6} C _inst_1 D _inst_2 F) (Prefunctor.obj.{max (succ u2) (succ u4), max (max (succ u2) (succ u6)) (succ u4), max (max (max u2 u6) u1) u4, max (max (succ u2) u6) (succ u4)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.CategoryStruct.toQuiver.{max u2 u4, max (max (max u2 u6) u1) u4} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Category.toCategoryStruct.{max u2 u4, max (max (max u2 u6) u1) u4} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u4, u2, u6} J _inst_3 D _inst_2))) (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.CategoryStruct.toQuiver.{max (max u2 u6) u4, max (max (succ u2) u6) (succ u4)} (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Category.toCategoryStruct.{max (max u2 u6) u4, max (max (succ u2) u6) (succ u4)} (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Functor.category.{u4, max u2 u4, u6, max (succ u2) (succ u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}))) (CategoryTheory.Functor.toPrefunctor.{max u2 u4, max (max u2 u6) u4, max (max (max u2 u6) u1) u4, max (max (succ u2) u6) (succ u4)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Functor.category.{u4, max u2 u4, u6, max (succ u2) (succ u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.cones.{u1, u4, u2, u6} J _inst_3 D _inst_2)) K))) X) -> (Prefunctor.obj.{succ u3, max (succ u2) (succ u3), u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.CategoryStruct.toQuiver.{u3, u5} (Opposite.{succ u5} C) (CategoryTheory.Category.toCategoryStruct.{u3, u5} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1))) Type.{max u2 u3} (CategoryTheory.CategoryStruct.toQuiver.{max u2 u3, max (succ u2) (succ u3)} Type.{max u2 u3} (CategoryTheory.Category.toCategoryStruct.{max u2 u3, max (succ u2) (succ u3)} Type.{max u2 u3} CategoryTheory.types.{max u2 u3})) (CategoryTheory.Functor.toPrefunctor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3} (Prefunctor.obj.{max (succ u2) (succ u3), max (max (succ u2) (succ u5)) (succ u3), max (max (max u2 u5) u1) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.CategoryStruct.toQuiver.{max u2 u3, max (max (max u2 u5) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Category.toCategoryStruct.{max u2 u3, max (max (max u2 u5) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 C _inst_1))) (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.CategoryStruct.toQuiver.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Category.toCategoryStruct.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}))) (CategoryTheory.Functor.toPrefunctor.{max u2 u3, max (max u2 u5) u3, max (max (max u2 u5) u1) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cones.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Functor.comp.{u1, u4, u3, u2, u6, u5} J _inst_3 D _inst_2 C _inst_1 K G))) X))
Case conversion may be inaccurate. Consider using '#align category_theory.adjunction.cones_iso_component_hom CategoryTheory.Adjunction.conesIsoComponentHomₓ'. -/
/-- auxiliary construction for `cones_iso` -/
@[simps]
def conesIsoComponentHom {J : Type u} [Category.{v} J] {K : J ⥤ D} (X : Cᵒᵖ)
    (t : (Functor.op F ⋙ (cones J D).obj K).obj X) : ((cones J C).obj (K ⋙ G)).obj X
    where
  app j := (adj.homEquiv (unop X) (K.obj j)) (t.app j)
  naturality' j j' f :=
    by
    erw [← adj.hom_equiv_naturality_right, ← t.naturality, category.id_comp, category.id_comp]
    rfl
#align category_theory.adjunction.cones_iso_component_hom CategoryTheory.Adjunction.conesIsoComponentHom

/- warning: category_theory.adjunction.cones_iso_component_inv -> CategoryTheory.Adjunction.conesIsoComponentInv is a dubious translation:
lean 3 declaration is
  forall {C : Type.{u5}} [_inst_1 : CategoryTheory.Category.{u3, u5} C] {D : Type.{u6}} [_inst_2 : CategoryTheory.Category.{u4, u6} D] {F : CategoryTheory.Functor.{u3, u4, u5, u6} C _inst_1 D _inst_2} {G : CategoryTheory.Functor.{u4, u3, u6, u5} D _inst_2 C _inst_1}, (CategoryTheory.Adjunction.{u3, u4, u5, u6} C _inst_1 D _inst_2 F G) -> (forall {J : Type.{u2}} [_inst_3 : CategoryTheory.Category.{u1, u2} J] {K : CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2} (X : Opposite.{succ u5} C), (CategoryTheory.Functor.obj.{u3, max u2 u3, u5, succ (max u2 u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3} (CategoryTheory.Functor.obj.{max u2 u3, max u5 u2 u3, max u1 u3 u2 u5, max u3 (max u2 u3) u5 (succ (max u2 u3))} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.{u3, max u2 u3, u5, succ (max u2 u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, succ (max u2 u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cones.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.comp.{u1, u4, u3, u2, u6, u5} J _inst_3 D _inst_2 C _inst_1 K G)) X) -> (CategoryTheory.Functor.obj.{u3, max u2 u4, u5, succ (max u2 u4)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u4} CategoryTheory.types.{max u2 u4} (CategoryTheory.Functor.comp.{u3, u4, max u2 u4, u5, u6, succ (max u2 u4)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4} (CategoryTheory.Functor.op.{u3, u4, u5, u6} C _inst_1 D _inst_2 F) (CategoryTheory.Functor.obj.{max u2 u4, max u6 u2 u4, max u1 u4 u2 u6, max u4 (max u2 u4) u6 (succ (max u2 u4))} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.{u4, max u2 u4, u6, succ (max u2 u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Functor.category.{u4, max u2 u4, u6, succ (max u2 u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.cones.{u1, u4, u2, u6} J _inst_3 D _inst_2) K)) X))
but is expected to have type
  forall {C : Type.{u5}} [_inst_1 : CategoryTheory.Category.{u3, u5} C] {D : Type.{u6}} [_inst_2 : CategoryTheory.Category.{u4, u6} D] {F : CategoryTheory.Functor.{u3, u4, u5, u6} C _inst_1 D _inst_2} {G : CategoryTheory.Functor.{u4, u3, u6, u5} D _inst_2 C _inst_1}, (CategoryTheory.Adjunction.{u3, u4, u5, u6} C _inst_1 D _inst_2 F G) -> (forall {J : Type.{u2}} [_inst_3 : CategoryTheory.Category.{u1, u2} J] {K : CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2} (X : Opposite.{succ u5} C), (Prefunctor.obj.{succ u3, max (succ u2) (succ u3), u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.CategoryStruct.toQuiver.{u3, u5} (Opposite.{succ u5} C) (CategoryTheory.Category.toCategoryStruct.{u3, u5} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1))) Type.{max u2 u3} (CategoryTheory.CategoryStruct.toQuiver.{max u2 u3, max (succ u2) (succ u3)} Type.{max u2 u3} (CategoryTheory.Category.toCategoryStruct.{max u2 u3, max (succ u2) (succ u3)} Type.{max u2 u3} CategoryTheory.types.{max u2 u3})) (CategoryTheory.Functor.toPrefunctor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3} (Prefunctor.obj.{max (succ u2) (succ u3), max (max (succ u2) (succ u5)) (succ u3), max (max (max u2 u5) u1) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.CategoryStruct.toQuiver.{max u2 u3, max (max (max u2 u5) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Category.toCategoryStruct.{max u2 u3, max (max (max u2 u5) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 C _inst_1))) (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.CategoryStruct.toQuiver.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Category.toCategoryStruct.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}))) (CategoryTheory.Functor.toPrefunctor.{max u2 u3, max (max u2 u5) u3, max (max (max u2 u5) u1) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 C _inst_1) (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cones.{u1, u3, u2, u5} J _inst_3 C _inst_1)) (CategoryTheory.Functor.comp.{u1, u4, u3, u2, u6, u5} J _inst_3 D _inst_2 C _inst_1 K G))) X) -> (Prefunctor.obj.{succ u3, max (succ u2) (succ u4), u5, max (succ u2) (succ u4)} (Opposite.{succ u5} C) (CategoryTheory.CategoryStruct.toQuiver.{u3, u5} (Opposite.{succ u5} C) (CategoryTheory.Category.toCategoryStruct.{u3, u5} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1))) Type.{max u2 u4} (CategoryTheory.CategoryStruct.toQuiver.{max u2 u4, max (succ u2) (succ u4)} Type.{max u2 u4} (CategoryTheory.Category.toCategoryStruct.{max u2 u4, max (succ u2) (succ u4)} Type.{max u2 u4} CategoryTheory.types.{max u2 u4})) (CategoryTheory.Functor.toPrefunctor.{u3, max u2 u4, u5, max (succ u2) (succ u4)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) Type.{max u2 u4} CategoryTheory.types.{max u2 u4} (CategoryTheory.Functor.comp.{u3, u4, max u2 u4, u5, u6, max (succ u2) (succ u4)} (Opposite.{succ u5} C) (CategoryTheory.Category.opposite.{u3, u5} C _inst_1) (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4} (CategoryTheory.Functor.op.{u3, u4, u5, u6} C _inst_1 D _inst_2 F) (Prefunctor.obj.{max (succ u2) (succ u4), max (max (succ u2) (succ u6)) (succ u4), max (max (max u2 u6) u1) u4, max (max (succ u2) u6) (succ u4)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.CategoryStruct.toQuiver.{max u2 u4, max (max (max u2 u6) u1) u4} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Category.toCategoryStruct.{max u2 u4, max (max (max u2 u6) u1) u4} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u4, u2, u6} J _inst_3 D _inst_2))) (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.CategoryStruct.toQuiver.{max (max u2 u6) u4, max (max (succ u2) u6) (succ u4)} (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Category.toCategoryStruct.{max (max u2 u6) u4, max (max (succ u2) u6) (succ u4)} (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Functor.category.{u4, max u2 u4, u6, max (succ u2) (succ u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}))) (CategoryTheory.Functor.toPrefunctor.{max u2 u4, max (max u2 u6) u4, max (max (max u2 u6) u1) u4, max (max (succ u2) u6) (succ u4)} (CategoryTheory.Functor.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u4, u2, u6} J _inst_3 D _inst_2) (CategoryTheory.Functor.{u4, max u2 u4, u6, max (succ u2) (succ u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.Functor.category.{u4, max u2 u4, u6, max (succ u2) (succ u4)} (Opposite.{succ u6} D) (CategoryTheory.Category.opposite.{u4, u6} D _inst_2) Type.{max u2 u4} CategoryTheory.types.{max u2 u4}) (CategoryTheory.cones.{u1, u4, u2, u6} J _inst_3 D _inst_2)) K))) X))
Case conversion may be inaccurate. Consider using '#align category_theory.adjunction.cones_iso_component_inv CategoryTheory.Adjunction.conesIsoComponentInvₓ'. -/
/-- auxiliary construction for `cones_iso` -/
@[simps]
def conesIsoComponentInv {J : Type u} [Category.{v} J] {K : J ⥤ D} (X : Cᵒᵖ)
    (t : ((cones J C).obj (K ⋙ G)).obj X) : (Functor.op F ⋙ (cones J D).obj K).obj X
    where
  app j := (adj.homEquiv (unop X) (K.obj j)).symm (t.app j)
  naturality' j j' f := by
    erw [← adj.hom_equiv_naturality_right_symm, ← t.naturality, category.id_comp, category.id_comp]
#align category_theory.adjunction.cones_iso_component_inv CategoryTheory.Adjunction.conesIsoComponentInv

end ArbitraryUniverse

variable {C : Type u₁} [Category.{v₀} C] {D : Type u₂} [Category.{v₀} D] {F : C ⥤ D} {G : D ⥤ C}
  (adj : F ⊣ G)

/- warning: category_theory.adjunction.cocones_iso -> CategoryTheory.Adjunction.coconesIso is a dubious translation:
lean 3 declaration is
  forall {C : Type.{u4}} [_inst_1 : CategoryTheory.Category.{u3, u4} C] {D : Type.{u5}} [_inst_2 : CategoryTheory.Category.{u3, u5} D] {F : CategoryTheory.Functor.{u3, u3, u4, u5} C _inst_1 D _inst_2} {G : CategoryTheory.Functor.{u3, u3, u5, u4} D _inst_2 C _inst_1}, (CategoryTheory.Adjunction.{u3, u3, u4, u5} C _inst_1 D _inst_2 F G) -> (forall {J : Type.{u2}} [_inst_3 : CategoryTheory.Category.{u1, u2} J] {K : CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1}, CategoryTheory.Iso.{max u5 u2 u3, max u3 (max u2 u3) u5 (succ (max u2 u3))} (CategoryTheory.Functor.{u3, max u2 u3, u5, succ (max u2 u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, succ (max u2 u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.obj.{max u2 u3, max u5 u2 u3, max u1 u3 u2 u5, max u3 (max u2 u3) u5 (succ (max u2 u3))} (Opposite.{succ (max u1 u3 u2 u5)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2)) (CategoryTheory.Category.opposite.{max u2 u3, max u1 u3 u2 u5} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 D _inst_2)) (CategoryTheory.Functor.{u3, max u2 u3, u5, succ (max u2 u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, succ (max u2 u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cocones.{u1, u3, u2, u5} J _inst_3 D _inst_2) (Opposite.op.{succ (max u1 u3 u2 u5)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2) (CategoryTheory.Functor.comp.{u1, u3, u3, u2, u4, u5} J _inst_3 C _inst_1 D _inst_2 K F))) (CategoryTheory.Functor.comp.{u3, u3, max u2 u3, u5, u4, succ (max u2 u3)} D _inst_2 C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3} G (CategoryTheory.Functor.obj.{max u2 u3, max u4 u2 u3, max u1 u3 u2 u4, max u3 (max u2 u3) u4 (succ (max u2 u3))} (Opposite.{succ (max u1 u3 u2 u4)} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1)) (CategoryTheory.Category.opposite.{max u2 u3, max u1 u3 u2 u4} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u4} J _inst_3 C _inst_1)) (CategoryTheory.Functor.{u3, max u2 u3, u4, succ (max u2 u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u4, succ (max u2 u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cocones.{u1, u3, u2, u4} J _inst_3 C _inst_1) (Opposite.op.{succ (max u1 u3 u2 u4)} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1) K))))
but is expected to have type
  forall {C : Type.{u4}} [_inst_1 : CategoryTheory.Category.{u3, u4} C] {D : Type.{u5}} [_inst_2 : CategoryTheory.Category.{u3, u5} D] {F : CategoryTheory.Functor.{u3, u3, u4, u5} C _inst_1 D _inst_2} {G : CategoryTheory.Functor.{u3, u3, u5, u4} D _inst_2 C _inst_1}, (CategoryTheory.Adjunction.{u3, u3, u4, u5} C _inst_1 D _inst_2 F G) -> (forall {J : Type.{u2}} [_inst_3 : CategoryTheory.Category.{u1, u2} J] {K : CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1}, CategoryTheory.Iso.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (Prefunctor.obj.{max (succ u2) (succ u3), max (max (succ u2) (succ u5)) (succ u3), max (max (max u2 u5) u1) u3, max (max (succ u2) u5) (succ u3)} (Opposite.{succ (max (max (max u5 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2)) (CategoryTheory.CategoryStruct.toQuiver.{max u2 u3, max (max (max u2 u5) u1) u3} (Opposite.{succ (max (max (max u5 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2)) (CategoryTheory.Category.toCategoryStruct.{max u2 u3, max (max (max u2 u5) u1) u3} (Opposite.{succ (max (max (max u5 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2)) (CategoryTheory.Category.opposite.{max u2 u3, max (max (max u2 u5) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 D _inst_2)))) (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.CategoryStruct.toQuiver.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Category.toCategoryStruct.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}))) (CategoryTheory.Functor.toPrefunctor.{max u2 u3, max (max u2 u5) u3, max (max (max u2 u5) u1) u3, max (max (succ u2) u5) (succ u3)} (Opposite.{succ (max (max (max u5 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2)) (CategoryTheory.Category.opposite.{max u2 u3, max (max (max u2 u5) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 D _inst_2)) (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} D _inst_2 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cocones.{u1, u3, u2, u5} J _inst_3 D _inst_2)) (Opposite.op.{max (max (max (succ u2) (succ u5)) (succ u1)) (succ u3)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2) (CategoryTheory.Functor.comp.{u1, u3, u3, u2, u4, u5} J _inst_3 C _inst_1 D _inst_2 K F))) (CategoryTheory.Functor.comp.{u3, u3, max u2 u3, u5, u4, max (succ u2) (succ u3)} D _inst_2 C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3} G (Prefunctor.obj.{max (succ u2) (succ u3), max (max (succ u2) (succ u4)) (succ u3), max (max (max u2 u4) u1) u3, max (max (succ u2) u4) (succ u3)} (Opposite.{succ (max (max (max u4 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1)) (CategoryTheory.CategoryStruct.toQuiver.{max u2 u3, max (max (max u2 u4) u1) u3} (Opposite.{succ (max (max (max u4 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1)) (CategoryTheory.Category.toCategoryStruct.{max u2 u3, max (max (max u2 u4) u1) u3} (Opposite.{succ (max (max (max u4 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1)) (CategoryTheory.Category.opposite.{max u2 u3, max (max (max u2 u4) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u4} J _inst_3 C _inst_1)))) (CategoryTheory.Functor.{u3, max u2 u3, u4, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.CategoryStruct.toQuiver.{max (max u2 u4) u3, max (max (succ u2) u4) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u4, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Category.toCategoryStruct.{max (max u2 u4) u3, max (max (succ u2) u4) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u4, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u4, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}))) (CategoryTheory.Functor.toPrefunctor.{max u2 u3, max (max u2 u4) u3, max (max (max u2 u4) u1) u3, max (max (succ u2) u4) (succ u3)} (Opposite.{succ (max (max (max u4 u2) u3) u1)} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1)) (CategoryTheory.Category.opposite.{max u2 u3, max (max (max u2 u4) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u4} J _inst_3 C _inst_1)) (CategoryTheory.Functor.{u3, max u2 u3, u4, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u4, max (succ u2) (succ u3)} C _inst_1 Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cocones.{u1, u3, u2, u4} J _inst_3 C _inst_1)) (Opposite.op.{max (max (max (succ u2) (succ u4)) (succ u1)) (succ u3)} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1) K))))
Case conversion may be inaccurate. Consider using '#align category_theory.adjunction.cocones_iso CategoryTheory.Adjunction.coconesIsoₓ'. -/
-- Note: this is natural in K, but we do not yet have the tools to formulate that.
/-- When `F ⊣ G`,
the functor associating to each `Y` the cocones over `K ⋙ F` with cone point `Y`
is naturally isomorphic to
the functor associating to each `Y` the cocones over `K` with cone point `G.obj Y`.
-/
def coconesIso {J : Type u} [Category.{v} J] {K : J ⥤ C} :
    (cocones J D).obj (op (K ⋙ F)) ≅ G ⋙ (cocones J C).obj (op K) :=
  NatIso.ofComponents
    (fun Y =>
      { Hom := coconesIsoComponentHom adj Y
        inv := coconesIsoComponentInv adj Y })
    (by tidy)
#align category_theory.adjunction.cocones_iso CategoryTheory.Adjunction.coconesIso

/- warning: category_theory.adjunction.cones_iso -> CategoryTheory.Adjunction.conesIso is a dubious translation:
lean 3 declaration is
  forall {C : Type.{u4}} [_inst_1 : CategoryTheory.Category.{u3, u4} C] {D : Type.{u5}} [_inst_2 : CategoryTheory.Category.{u3, u5} D] {F : CategoryTheory.Functor.{u3, u3, u4, u5} C _inst_1 D _inst_2} {G : CategoryTheory.Functor.{u3, u3, u5, u4} D _inst_2 C _inst_1}, (CategoryTheory.Adjunction.{u3, u3, u4, u5} C _inst_1 D _inst_2 F G) -> (forall {J : Type.{u2}} [_inst_3 : CategoryTheory.Category.{u1, u2} J] {K : CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2}, CategoryTheory.Iso.{max u4 u2 u3, max u3 (max u2 u3) u4 (succ (max u2 u3))} (CategoryTheory.Functor.{u3, max u2 u3, u4, succ (max u2 u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u4, succ (max u2 u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.comp.{u3, u3, max u2 u3, u4, u5, succ (max u2 u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) (Opposite.{succ u5} D) (CategoryTheory.Category.opposite.{u3, u5} D _inst_2) Type.{max u2 u3} CategoryTheory.types.{max u2 u3} (CategoryTheory.Functor.op.{u3, u3, u4, u5} C _inst_1 D _inst_2 F) (CategoryTheory.Functor.obj.{max u2 u3, max u5 u2 u3, max u1 u3 u2 u5, max u3 (max u2 u3) u5 (succ (max u2 u3))} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 D _inst_2) (CategoryTheory.Functor.{u3, max u2 u3, u5, succ (max u2 u3)} (Opposite.{succ u5} D) (CategoryTheory.Category.opposite.{u3, u5} D _inst_2) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, succ (max u2 u3)} (Opposite.{succ u5} D) (CategoryTheory.Category.opposite.{u3, u5} D _inst_2) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cones.{u1, u3, u2, u5} J _inst_3 D _inst_2) K)) (CategoryTheory.Functor.obj.{max u2 u3, max u4 u2 u3, max u1 u3 u2 u4, max u3 (max u2 u3) u4 (succ (max u2 u3))} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u4} J _inst_3 C _inst_1) (CategoryTheory.Functor.{u3, max u2 u3, u4, succ (max u2 u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u4, succ (max u2 u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cones.{u1, u3, u2, u4} J _inst_3 C _inst_1) (CategoryTheory.Functor.comp.{u1, u3, u3, u2, u5, u4} J _inst_3 D _inst_2 C _inst_1 K G)))
but is expected to have type
  forall {C : Type.{u4}} [_inst_1 : CategoryTheory.Category.{u3, u4} C] {D : Type.{u5}} [_inst_2 : CategoryTheory.Category.{u3, u5} D] {F : CategoryTheory.Functor.{u3, u3, u4, u5} C _inst_1 D _inst_2} {G : CategoryTheory.Functor.{u3, u3, u5, u4} D _inst_2 C _inst_1}, (CategoryTheory.Adjunction.{u3, u3, u4, u5} C _inst_1 D _inst_2 F G) -> (forall {J : Type.{u2}} [_inst_3 : CategoryTheory.Category.{u1, u2} J] {K : CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2}, CategoryTheory.Iso.{max (max u2 u4) u3, max (max (max (max (succ u2) (succ u3)) u4) u2 u3) u3} (CategoryTheory.Functor.{u3, max u2 u3, u4, max (succ u2) (succ u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u4, max (succ u2) (succ u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.comp.{u3, u3, max u2 u3, u4, u5, max (succ u2) (succ u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) (Opposite.{succ u5} D) (CategoryTheory.Category.opposite.{u3, u5} D _inst_2) Type.{max u2 u3} CategoryTheory.types.{max u2 u3} (CategoryTheory.Functor.op.{u3, u3, u4, u5} C _inst_1 D _inst_2 F) (Prefunctor.obj.{max (succ u2) (succ u3), max (max (succ u2) (succ u5)) (succ u3), max (max (max u2 u5) u1) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2) (CategoryTheory.CategoryStruct.toQuiver.{max u2 u3, max (max (max u2 u5) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2) (CategoryTheory.Category.toCategoryStruct.{max u2 u3, max (max (max u2 u5) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 D _inst_2))) (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} D) (CategoryTheory.Category.opposite.{u3, u5} D _inst_2) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.CategoryStruct.toQuiver.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} D) (CategoryTheory.Category.opposite.{u3, u5} D _inst_2) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Category.toCategoryStruct.{max (max u2 u5) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} D) (CategoryTheory.Category.opposite.{u3, u5} D _inst_2) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} D) (CategoryTheory.Category.opposite.{u3, u5} D _inst_2) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}))) (CategoryTheory.Functor.toPrefunctor.{max u2 u3, max (max u2 u5) u3, max (max (max u2 u5) u1) u3, max (max (succ u2) u5) (succ u3)} (CategoryTheory.Functor.{u1, u3, u2, u5} J _inst_3 D _inst_2) (CategoryTheory.Functor.category.{u1, u3, u2, u5} J _inst_3 D _inst_2) (CategoryTheory.Functor.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} D) (CategoryTheory.Category.opposite.{u3, u5} D _inst_2) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u5, max (succ u2) (succ u3)} (Opposite.{succ u5} D) (CategoryTheory.Category.opposite.{u3, u5} D _inst_2) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cones.{u1, u3, u2, u5} J _inst_3 D _inst_2)) K)) (Prefunctor.obj.{max (succ u2) (succ u3), max (max (succ u2) (succ u4)) (succ u3), max (max (max u2 u4) u1) u3, max (max (succ u2) u4) (succ u3)} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1) (CategoryTheory.CategoryStruct.toQuiver.{max u2 u3, max (max (max u2 u4) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1) (CategoryTheory.Category.toCategoryStruct.{max u2 u3, max (max (max u2 u4) u1) u3} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u4} J _inst_3 C _inst_1))) (CategoryTheory.Functor.{u3, max u2 u3, u4, max (succ u2) (succ u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.CategoryStruct.toQuiver.{max (max u2 u4) u3, max (max (succ u2) u4) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u4, max (succ u2) (succ u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Category.toCategoryStruct.{max (max u2 u4) u3, max (max (succ u2) u4) (succ u3)} (CategoryTheory.Functor.{u3, max u2 u3, u4, max (succ u2) (succ u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u4, max (succ u2) (succ u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}))) (CategoryTheory.Functor.toPrefunctor.{max u2 u3, max (max u2 u4) u3, max (max (max u2 u4) u1) u3, max (max (succ u2) u4) (succ u3)} (CategoryTheory.Functor.{u1, u3, u2, u4} J _inst_3 C _inst_1) (CategoryTheory.Functor.category.{u1, u3, u2, u4} J _inst_3 C _inst_1) (CategoryTheory.Functor.{u3, max u2 u3, u4, max (succ u2) (succ u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.Functor.category.{u3, max u2 u3, u4, max (succ u2) (succ u3)} (Opposite.{succ u4} C) (CategoryTheory.Category.opposite.{u3, u4} C _inst_1) Type.{max u2 u3} CategoryTheory.types.{max u2 u3}) (CategoryTheory.cones.{u1, u3, u2, u4} J _inst_3 C _inst_1)) (CategoryTheory.Functor.comp.{u1, u3, u3, u2, u5, u4} J _inst_3 D _inst_2 C _inst_1 K G)))
Case conversion may be inaccurate. Consider using '#align category_theory.adjunction.cones_iso CategoryTheory.Adjunction.conesIsoₓ'. -/
-- Note: this is natural in K, but we do not yet have the tools to formulate that.
/-- When `F ⊣ G`,
the functor associating to each `X` the cones over `K` with cone point `F.op.obj X`
is naturally isomorphic to
the functor associating to each `X` the cones over `K ⋙ G` with cone point `X`.
-/
def conesIso {J : Type u} [Category.{v} J] {K : J ⥤ D} :
    F.op ⋙ (cones J D).obj K ≅ (cones J C).obj (K ⋙ G) :=
  NatIso.ofComponents
    (fun X =>
      { Hom := conesIsoComponentHom adj X
        inv := conesIsoComponentInv adj X })
    (by tidy)
#align category_theory.adjunction.cones_iso CategoryTheory.Adjunction.conesIso

end CategoryTheory.Adjunction


import SciLean.Algebra
import SciLean.Quot.Monomial

namespace SciLean

namespace Algebra

  -- M monomials
  -- K ring
  inductive Repr (M K X : Type u) : Type u where
  | mon (m : M) : Repr M K X
  | add (x y : Repr M K X) : Repr M K X
  | mul (x y : Repr M K X) : Repr M K X
  | lmul (c : K) (x : Repr M K X) : Repr M K X
  -- | rmul (x : Repr M K) (c : K) : Repr M K

  instance {M K X} : Mul (Repr M K X) := ⟨λ x y => Repr.mul x y⟩
  instance {M K X} : Add (Repr M K X) := ⟨λ x y => Repr.add x y⟩
  instance {M K X} : HMul K (Repr M K X) (Repr M K X) := ⟨λ x y => Repr.lmul x y⟩
  -- instance {M K} : HMul (Repr M K) K (Repr M K) := ⟨λ x y => Repr.rmul x y⟩

  instance {M K X} [Zero M] : Zero (Repr M K X) := ⟨Repr.mon 0⟩
  instance {M K X} [One M]  : One (Repr M K X)  := ⟨Repr.mon 1⟩

  namespace Repr

    def toString {M K X} (s_add s_mul s_lmul : String) [ToString M] [ToString K] (x : Repr M K X) : String :=
      match x with
      | mon m => s!"{m}"
      | add x y => s!"({toString s_add s_mul s_lmul x}{s_add}{toString s_add s_mul s_lmul y})"
      | mul x y => s!"{toString s_add s_mul s_lmul x}{s_mul}{toString s_add s_mul s_lmul y}"
      | lmul c x => s!"{c}{s_lmul}{toString s_add s_mul s_lmul x}"

    instance {M K X} [ToString M] [ToString K] : ToString (Repr M K X) :=
    ⟨ λ x => x.toString " + " " * " " * "⟩

    def RedFormFromNot {M K X} (notForm : Repr M K X → Prop) (x : Repr M K X) : Prop :=
      match x with
      | mon x => ¬ (notForm (mon x))
      | x + y => ¬ (notForm x) ∧ ¬ (notForm y) ∧ ¬ (notForm (x + y))
      | x * y => ¬ (notForm x) ∧ ¬ (notForm y) ∧ ¬ (notForm (x * y))
      | lmul c x => ¬ (notForm x) ∧ ¬ (notForm (c * x))

    -- Rather defining reduced form we define what can't occur in reduced form
    inductive NotRed1Form {M K X} : Repr M K X → Prop where
    -- monomials should be multiplied together
    | red1_mon (m m' : M)                         : NotRed1Form ((mon m) * (mon m'))
    -- left multiplication association
    | red1_mul_assoc (x y z : Repr M K X)         : NotRed1Form (x*(y*z))
    -- scalar multiplication always on the left
    | red1_mul_lmul (x y : Repr M K X) (c : K)    : NotRed1Form (x * (c * y))
    -- no scalar multiplication on monomial
    | red1_lmul_mon (m : M) (c : K)               : NotRed1Form (c * (mon m : Repr M K X))
    -- no double scalar multiplication
    | red1_lmul_lmul (x : Repr M K X) (c c' : K)  : NotRed1Form (c * (c' * x))
    -- left addition association
    | red1_add_assoc (x y z : Repr M K X)         : NotRed1Form (x + (y + z))

    def Red1Form {M K X} : Repr M K X → Prop := RedFormFromNot NotRed1Form

    partial def reduce1 {M K X} [Add K] [Mul K] [Zero K] [Monomial M K X] -- [DecidableEq M] --[Monomial M X K]
      (x : Repr M K X) : Repr M K X
      :=
      match x with
      | x * y =>
        match reduce1 x, reduce1 y with
        | mon x, mon y => mon (x*y)
        | x, lmul c y' => reduce1 $ (reduce1 $ lmul c x) * y'
        | x, y' * y'' => reduce1 $ x * y' * y''
        | x, y => x * y
      | lmul c x =>
        match reduce1 x with
        | mon x => mon (c*x)
        | x * y => reduce1 (c*x)*y
        | lmul d x => (c*d)*x
        | x => c * x
      | x + y =>
        match reduce1 x, reduce1 y with
        | x, y' + y'' => reduce1 $ (x + y') + y''
        | x, y => x + y
      | x => x

    @[simp]
    theorem reduce1_idempotent {M K X} [Add K] [Mul K] [Zero K] [Monomial M K X]
      (x : Repr M K X) : reduce1 (reduce1 x) = reduce1 x := sorry

    theorem reduce1_sound {M K X} [Add K] [Mul K] [Zero K] [Monomial M K X]
      (x : Repr M K X) : Red1Form (reduce1 x) := sorry

    inductive NotRed2Form {M K X} [Zero M] [LT X] [Monomial M K X] : Repr M K X → Prop where
    -- reduced2 implies reduce1
    | red2_red1 (x : Repr M K X) (h : NotRed1Form x) : NotRed2Form x
    -- addition of monomials of the same base not allowed
    | red2_mon_base (m m' : M) (h : Monomial.base K m = (Monomial.base K m' : X)) : NotRed2Form (mon m + mon m')
    -- addition of monomials has to be in correct order
    | red2_mon_order (m m' : M) (h : Monomial.base K m > (Monomial.base K m' : X)) : NotRed2Form (mon m + mon m')
    -- can't add zero
    | red2_add_zero (x : Repr M K X) : NotRed2Form (x + 0)
    -- can't add to zero
    | red2_zero_add (x : Repr M K X) : NotRed2Form (0 + x)
    -- TODO: Finish the definition
    -- | red2_add_base (x y : Repr M K X) :

    def Red2Form {M K X} [Zero M] [LT X] [Monomial M K X] : Repr M K X → Prop := RedFormFromNot NotRed2Form

    open Monomial
    partial def reduce2 {M K X} [Add K] [Mul K] [Zero K] [Monomial M K X]
      [DecidableEq M] [Zero M] [One M]
      [DecidableEq K] [LT X] [DecidableCp X]
      (x : Repr M K X) : Repr M K X
      :=
      match reduce1 x with
      | x + y =>
        match reduce2 x, reduce2 y with
        | mon x', mon y' =>
          match decCp (base K x') ((base K y') : X) with
          | cpEq h => reduce2 $ mon $ intro ((coef X x' + coef X y') : K) ((base K x') : X)
          | cpLt h => if x' = 0 then mon y' else mon x' + mon y'
          | cpGt h => if y' = 0 then mon x' else mon y' + mon x'
        | x'' + mon x', mon y' =>
          match decCp (base K x') ((base K y') : X) with
          | cpEq h => reduce2 $ x'' + (mon $ intro ((coef X x' + coef X y') : K) ((base K x') : X))
          | cpLt h => if x' = 0 then x'' + mon y' else x'' + mon x' + mon y'
          | cpGt h => reduce2 $ if y' = 0 then x'' + mon x' else x'' + mon y' + mon x'
        | x', y' => x' + y'
      | x * y =>
        match reduce2 x, reduce2 y with
        | mon x', mon y' => mon (x'*y')
        | mon x', y' =>
          if x' = 0
          then mon 0
          else if x' = 1
          then y'
          else mon x' * y'
        | x', mon y' =>
          if y' = 0
          then mon 0
          else if y' = 1
          then x'
          else x' * mon y'
        | x', y' => x' * y'
      | lmul c x =>
        if c = 0 then
          mon 0
        else
          reduce1 $ lmul c (reduce2 x)
      | x => x

    @[simp]
    theorem reduce2_idempotent  {M K X} [Add K] [Mul K] [Zero K] [Monomial M K X]
      [DecidableEq M] [Zero M] [One M]
      [DecidableEq K] [LT X] [DecidableCp X]
      (x : Repr M K X) : reduce2 (reduce2 x) = reduce2 x := sorry

    theorem reduce2_sound  {M K X} [Add K] [Mul K] [Zero K] [Monomial M K X]
      [DecidableEq M] [Zero M] [One M]
      [DecidableEq K] [LT X] [DecidableCp X]
      (x : Repr M K X) : Red2Form (reduce2 x) := sorry

    -- Normalized form is fully expanded polynomial where terms are ordered by their degree
    inductive NotNormForm {M K X} [Zero M] [LT X] [Monomial M K X] : Repr M K X → Prop where
    -- reduced2 implies reduce1
    | norm_red2 (x : Repr M K X) (h : NotRed2Form x) : NotNormForm x
    -- addition of monomials of the same base not allowed
    | norm_mul (x y : Repr M K X) : NotNormForm (x * y)

    def NormForm {M K X} [Zero M] [LT X] [Monomial M K X] : Repr M K X → Prop := RedFormFromNot NotNormForm

    open Monomial
    partial def normalize {M K X} [Add K] [Mul K] [Zero K] [Monomial M K X]
      [DecidableEq M] [Zero M] [One M]
      [DecidableEq K] [LT X] [DecidableCp X]
      (x : Repr M K X) : Repr M K X
      :=
    match reduce2 x with
    | x * y =>
      match normalize x, normalize y with
      | x', y' + y'' => normalize (x' * y' + x' * y'')
      | x' + x'', y' => normalize (x' * y' + x'' * y')
      | x', y' => reduce2 $ x' * y'
    -- | x * (y + z) => normalize (x * y + x * z)
    -- | (x + y) * z => normalize (x * z + y * z)
    | x + y => reduce2 $ normalize x + normalize y
    | lmul c (x + y) => normalize (c * x + c * y)
    | x => x

    @[simp]
    theorem normalize_idempotent  {M K X} [Add K] [Mul K] [Zero K] [Monomial M K X]
      [DecidableEq M] [Zero M] [One M]
      [DecidableEq K] [LT X] [DecidableCp X]
      (x : Repr M K X) : normalize (normalize x) = normalize x := sorry

    theorem normalize_sound  {M K X} [Add K] [Mul K] [Zero K] [Monomial M K X]
      [DecidableEq M] [Zero M] [One M]
      [DecidableEq K] [LT X] [DecidableCp X]
      (x : Repr M K X) : NormForm (normalize x) := sorry

    open Monomial in
    inductive AlgEq (M K X) [Zero M] [One M] [Add K] [LT X] [Monomial M K X] : Repr M K X → Repr M K X → Prop where
    | add_assoc (x y z : Repr M K X) : AlgEq M K X ((x + y) + z) (x + (y + z))
    | add_comm  (x y : Repr M K X) : AlgEq M K X (x + y) (y + x)
    | add_mon  (m m' : M) (h : base K m = (base K m' : X))
      : AlgEq M K X (mon m + mon m') (mon $ intro (coef X m + coef X m' : K) (base K m : X))
    | add_zero  (x : Repr M K X) : AlgEq M K X (x + 0) x

    | mul_assoc (x y z : Repr M K X) : AlgEq M K X ((x * y) * z) (x * (y * z))
    | mul_mon   (m m' : M) : AlgEq M K X (mon m * mon m') (mon (m * m'))
    | mul_zero  (x y : Repr M K X) : AlgEq M K X (1 * x) x

    | mul_add  (x y z : Repr M K X) : AlgEq M K X (x * (y + z)) (x * y + x * z)
    | lmul_add  (c : K )(x y : Repr M K X) : AlgEq M K X (c * (x + y)) (c * x + c * y)

    | lmul_mon  (c : K) (m : M) : AlgEq M K X (lmul c (mon m)) (mon (c * m))
    -- TODO: Am I missing something here?

    open Quot' in
    instance {M K X} [Zero M] [One M] [Add K] [LT X] [Monomial M K X] : QForm (AlgEq M K X) :=
    {
      RedForm  := λ lvl x =>
        match lvl with
        | redLvl 0 => True
        | redLvl 1 => Red1Form x
        | redLvl n => Red2Form x
        | normLvl  => NormForm x
      redform_norm := sorry
      redform_zero := sorry
      redform_succ := sorry
      redform_inf  := sorry
    }

    open Quot'

    instance {M K X} [Zero M] [One M] [Add K] [Mul K] [Zero K] [LT X] [Monomial M K X] : QReduce (AlgEq M K X) (redLvl 1) :=
    {
      reduce := λ x => x.reduce1
      is_reduce := sorry
      eq_reduce := sorry
      preserve_stronger := sorry
    }

    instance {M K X} [Add K] [Mul K] [Zero K] [Monomial M K X]
      [DecidableEq M] [Zero M] [One M]
      [DecidableEq K] [LT X] [DecidableCp X]
      [Monomial M K X] : QReduce (AlgEq M K X) (redLvl 2) :=
    {
      reduce := λ x => x.reduce2
      is_reduce := sorry
      eq_reduce := sorry
      preserve_stronger := sorry
    }

    instance {M K X} [Add K] [Mul K] [Zero K] [Monomial M K X]
      [DecidableEq M] [Zero M] [One M]
      [DecidableEq K] [LT X] [DecidableCp X]
      [Monomial M K X] : QReduce (AlgEq M K X) (normLvl) :=
    {
      reduce := λ x => x.normalize
      is_reduce := sorry
      eq_reduce := sorry
      preserve_stronger := sorry
    }

  end Repr

  namespace Test

    open Quot'

    abbrev Rep := Repr (SymMonomial Int Nat) Int (FreeMonoid Nat)

    def one : Rep := Repr.mon (⟦⟨⟨1, ⟨[]⟩⟩, normLvl, sorry⟩⟧)
    def x : Rep := Repr.mon (⟦⟨⟨1, ⟨[0]⟩⟩, normLvl, sorry⟩⟧)
    def y : Rep := Repr.mon (⟦⟨⟨1, ⟨[1]⟩⟩, normLvl, sorry⟩⟧)

    example : (x * (x * y) * x |>.reduce1 |> toString) = "[0]*[0]*[0]*[1]" := by native_decide
    example : (y * ((2:ℤ)*x) * ((3:ℤ)*x) |>.reduce1 |> toString) = "6*[0]*[0]*[1]" := by native_decide
    example : ((x*y + ((x + y*x) + x) + y) |>.reduce1 |> toString) = "(((([0]*[1] + [0]) + [0]*[1]) + [0]) + [1])" := by native_decide
    example : ((2:ℤ)*x + (3:ℤ)*x*((5:ℤ)*(x + y)) |>.reduce1 |> toString) = "(2*[0] + 15*[0] * ([0] + [1]))" := by native_decide

    example : ((x + x) |>.reduce2 |> toString) = "2*[0]" := by native_decide
    example : ((x + y + x) |>.reduce2 |> toString) = "(2*[0] + [1])" := by native_decide
    example : (x + (x + y) |>.reduce2 |> toString) = "(2*[0] + [1])" := by native_decide
    example : (x + x + y + (-1:ℤ)*x |>.reduce2 |> toString) = "([0] + [1])" := by native_decide
    example : ((2:ℤ)*x + x*((0:ℤ)*x + (0:ℤ)*y) |>.reduce2 |> toString) = "2*[0]" := by native_decide
    example : ((2:ℤ)*x + x*((0:ℤ)*x + (0:ℤ)*y + one) |>.reduce2 |> toString) = "3*[0]" := by native_decide
    example : ((2:ℤ)*x + (5:ℤ)*((2:ℤ)*x + x + (0:ℤ)*y) |>.reduce2 |> toString) = "17*[0]" := by native_decide
    example : (((2:ℤ)*x + y)*((2:ℤ)*x + (1:ℤ)*y + (10:ℤ)*one + x*y) |>.reduce2 |> toString)
              = "(2*[0] + [1]) * (((10*1 + 2*[0]) + [1]) + [0]*[1])" := by native_decide

    example : ((5:ℤ)*(x + y)*((2:ℤ)*x + x + (3:ℤ)*y) |>.normalize |> toString)
              = "((15*[0]*[0] + 30*[0]*[1]) + 15*[1]*[1])" := by native_decide
    example : (((2:ℤ)*x + y)*((2:ℤ)*x + (1:ℤ)*y + (10:ℤ)*one + x*y) |>.normalize |> toString)
              = "((((((20*[0] + 10*[1]) + 4*[0]*[0]) + 4*[0]*[1]) + [1]*[1]) + 2*[0]*[0]*[1]) + [0]*[1]*[1])" := by native_decide
    example : ((2:ℤ)*x + (3:ℤ)*x*((5:ℤ)*(x + y)) |>.normalize |> toString)
              = "((2*[0] + 15*[0]*[0]) + 15*[0]*[1])" := by native_decide

  end Test

end Algebra

-- Algebra that reduces to specified level
abbrev Algebra (M K X) (lvl := Quot'.redLvl 1) [MonoidWithZero M] [Ring K] [LT X] [Monomial M K X] := Quot' (Algebra.Repr.AlgEq M K X)

namespace Algebra

  open Quot'

  variable {M K X lvl} [MonoidWithZero M] [Ring K] [LT X] [Monomial M K X] [QReduce (Algebra.Repr.AlgEq M K X) lvl]

  instance : Add (Algebra M K X lvl) := ⟨λ x' y' => reduce lvl <| Quot'.lift₂ (λ x y => x + y) (hom := sorry) x' y'⟩
  instance [One K] [Neg K] : Neg (Algebra M K X lvl) := ⟨λ x' => reduce lvl <| Quot'.lift (λ x => (-1 : K)*x) (hom := sorry) x'⟩
  instance [One K] [Neg K] : Sub (Algebra M K X lvl) := ⟨λ x' y' => reduce lvl <| Quot'.lift₂ (λ x y => x + (-1 : K)*y) (hom := sorry) x' y'⟩
  instance : Mul (Algebra M K X lvl) := ⟨λ x' y' => reduce lvl <| Quot'.lift₂ (λ x y => x * y) (hom := sorry) x' y'⟩
  instance : HMul K (Algebra M K X lvl) (Algebra M K X lvl) := ⟨λ c x' => reduce lvl <| Quot'.lift (λ x => c * x) (hom := sorry) x'⟩

  instance : One (Algebra M K X lvl) := ⟨⟦⟨Repr.mon 1, normLvl, sorry⟩⟧⟩
  instance : Zero (Algebra M K X lvl) := ⟨⟦⟨Repr.mon 0, normLvl, sorry⟩⟧⟩

  -- instance (n : Nat) : OfNat (Algebra M K X lvl) n := ⟨(n : K)*(1 : Algebra M K X lvl)⟩

  -- instance : Numeric (Algebra M K X lvl) := ⟨λ n => (OfNat.ofNat n : K)*(1 : Algebra M K X lvl)⟩

  instance : AddSemigroup (Algebra M K X lvl) :=
  {
    add_assoc := sorry
  }

  instance : AddCommSemigroup (Algebra M K X lvl) :=
  {
    add_comm := sorry
  }

  instance : Semigroup (Algebra M K X lvl) :=
  {
    mul_assoc := sorry
  }

  instance : Semiring (Algebra M K X lvl) where
    add_zero := sorry
    zero_add := sorry
    nsmul_zero' := sorry
    nsmul_succ' := sorry
    zero_mul := sorry
    mul_zero := sorry
    one_mul := sorry
    mul_one := sorry
    npow_zero' := sorry
    npow_succ' := sorry

    add_comm := sorry
    left_distrib := sorry
    right_distrib := sorry

    mul_assoc := sorry

    natCast n := (n : K)*(1 : Algebra M K X lvl)
    natCast_zero := sorry
    natCast_succ := sorry

    -- mul_add := sorry
    -- add_mul := sorry
    -- ofNat_succ := sorry

  instance : Ring (Algebra M K X lvl) where
    sub_eq_add_neg := sorry
    gsmul_zero' := sorry
    gsmul_succ' := sorry
    gsmul_neg' := sorry
    add_left_neg := sorry

    intCast n := (n : K)*(1 : Algebra M K X lvl)
    intCast_ofNat := sorry
    intCast_negSucc := sorry

end Algebra

abbrev Polynomial (K ι) [Ring K] [DecidableEq K] [LT ι] [DecidableCp ι]
  := Algebra (SymMonomial K ι) K (FreeMonoid ι) (lvl := Quot'.redLvl 2)

abbrev AltPolynomial (K ι) [Ring K] [DecidableEq K] [LT ι] [DecidableCp ι]
  := Algebra (AltMonomial K ι) K (FreeMonoid ι) (lvl := Quot'.redLvl 2)

namespace Polynomial

  open Algebra.Repr

  open Quot'

  def x : Polynomial Int Nat := ⟦⟨mon ⟦⟨⟨1, ⟨[0]⟩⟩, normLvl, sorry⟩⟧, normLvl, sorry⟩⟧
  def xx : Polynomial Int Nat := ⟦⟨mon ⟦⟨⟨1, ⟨[0,0]⟩⟩, normLvl, sorry⟩⟧, normLvl, sorry⟩⟧
  def y : Polynomial Int Nat := ⟦⟨mon ⟦⟨⟨1, ⟨[1]⟩⟩, normLvl, sorry⟩⟧, normLvl, sorry⟩⟧

  set_option synthInstance.maxHeartbeats 5000
  #eval ((x + y + x - y + 1*x*x) * x).toDebugString

  #eval (x -y + (x + y - x) + (x + y + x - y + 1*x*x) * x) |> Quot'.normalize |>.toDebugString
  #eval (x -y + (x + y - x) + (x + y + x - y + 1*x*x) * x) |>.toDebugString

  #eval (-y + (x + y - x) + (x + y ) * x).toDebugString

end Polynomial


/-
Copyright (c) 2018 Kenny Lau. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Yury Kudryashov

! This file was ported from Lean 3 source module algebra.algebra.pi
! leanprover-community/mathlib commit b16045e4bf61c6fd619a1a68854ab3d605dcd017
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Algebra.Algebra.Equiv

/-!
# The R-algebra structure on families of R-algebras

The R-algebra structure on `∀ i : I, A i` when each `A i` is an R-algebra.

## Main defintions

* `Pi.algebra`
* `Pi.evalAlgHom`
* `Pi.constAlgHom`
-/

universe u v w

namespace Pi

variable {I : Type u}

-- The indexing type
variable {R : Type _}

-- The scalar type
variable {f : I → Type v}

-- The family of types already equipped with instances
variable (x y : ∀ i, f i) (i : I)

variable (I f)

instance algebra {r : CommSemiring R} [s : ∀ i, Semiring (f i)] [∀ i, Algebra R (f i)] :
    Algebra R (∀ i : I, f i) :=
  {
    (Pi.ringHom fun i => algebraMap R (f i) :
      R →+* ∀ i : I,
          f i) with
    commutes' := fun a f => by ext; simp [Algebra.commutes]
    smul_def' := fun a f => by ext; simp [Algebra.smul_def] }
#align pi.algebra Pi.algebra

theorem algebraMap_def {_ : CommSemiring R} [_s : ∀ i, Semiring (f i)] [∀ i, Algebra R (f i)]
    (a : R) : algebraMap R (∀ i, f i) a = fun i => algebraMap R (f i) a :=
  rfl
#align pi.algebra_map_def Pi.algebraMap_def

@[simp]
theorem algebraMap_apply {_ : CommSemiring R} [_s : ∀ i, Semiring (f i)] [∀ i, Algebra R (f i)]
    (a : R) (i : I) : algebraMap R (∀ i, f i) a i = algebraMap R (f i) a :=
  rfl
#align pi.algebra_map_apply Pi.algebraMap_apply

-- One could also build a `∀ i, R i`-algebra structure on `∀ i, A i`,
-- when each `A i` is an `R i`-algebra, although I'm not sure that it's useful.
variable {I} (R)

/-- `Function.eval` as an `AlgHom`. The name matches `Pi.evalRingHom`, `Pi.evalMonoidHom`,
etc. -/
@[simps]
def evalAlgHom {_ : CommSemiring R} [∀ i, Semiring (f i)] [∀ i, Algebra R (f i)] (i : I) :
    (∀ i, f i) →ₐ[R] f i :=
  { Pi.evalRingHom f i with
    toFun := fun f => f i
    commutes' := fun _ => rfl }
#align pi.eval_alg_hom Pi.evalAlgHom

variable (A B : Type _) [CommSemiring R] [Semiring B] [Algebra R B]

/-- `Function.const` as an `AlgHom`. The name matches `Pi.constRingHhom`, `Pi.constMonoidHom`,
etc. -/
@[simps]
def constAlgHom : B →ₐ[R] A → B :=
  { Pi.constRingHom A B with
    toFun := Function.const _
    commutes' := fun _ => rfl }
#align pi.const_alg_hom Pi.constAlgHom

/-- When `R` is commutative and permits an `algebraMap`, `Pi.constRingHom` is equal to that
map. -/
@[simp]
theorem constRingHom_eq_algebraMap : constRingHom A R = algebraMap R (A → R) :=
  rfl
#align pi.const_ring_hom_eq_algebra_map Pi.constRingHom_eq_algebraMap

@[simp]
theorem constAlgHom_eq_algebra_ofId : constAlgHom R A R = Algebra.ofId R (A → R) :=
  rfl
#align pi.const_alg_hom_eq_algebra_of_id Pi.constAlgHom_eq_algebra_ofId

end Pi

/-- A special case of `Pi.algebra` for non-dependent types. Lean struggles to elaborate
definitions elsewhere in the library without this, -/
instance Function.algebra {R : Type _} (I : Type _) (A : Type _) [CommSemiring R] [Semiring A]
    [Algebra R A] : Algebra R (I → A) :=
  Pi.algebra _ _
#align function.algebra Function.algebra

namespace AlgHom

variable {R : Type u} {A : Type v} {B : Type w} {I : Type _}

variable [CommSemiring R] [Semiring A] [Semiring B]

variable [Algebra R A] [Algebra R B]

/-- `R`-algebra homomorphism between the function spaces `I → A` and `I → B`, induced by an
`R`-algebra homomorphism `f` between `A` and `B`. -/
@[simps]
protected def compLeft (f : A →ₐ[R] B) (I : Type _) : (I → A) →ₐ[R] I → B :=
  { f.toRingHom.compLeft I with
    toFun := fun h => f ∘ h
    commutes' := fun c => by
      ext
      exact f.commutes' c }
#align alg_hom.comp_left AlgHom.compLeft

end AlgHom

namespace AlgEquiv

/-- A family of algebra equivalences `∀ i, (A₁ i ≃ₐ A₂ i)` generates a
multiplicative equivalence between `∀ i, A₁ i` and `∀ i, A₂ i`.

This is the `AlgEquiv` version of `Equiv.Pi_congrRight`, and the dependent version of
`AlgEquiv.arrowCongr`.
-/
@[simps apply]
def piCongrRight {R ι : Type _} {A₁ A₂ : ι → Type _} [CommSemiring R] [∀ i, Semiring (A₁ i)]
    [∀ i, Semiring (A₂ i)] [∀ i, Algebra R (A₁ i)] [∀ i, Algebra R (A₂ i)]
    (e : ∀ i, A₁ i ≃ₐ[R] A₂ i) : (∀ i, A₁ i) ≃ₐ[R] ∀ i, A₂ i :=
  {
    @RingEquiv.piCongrRight ι A₁ A₂ _ _ fun i =>
      (e i).toRingEquiv with
    toFun := fun x j => e j (x j)
    invFun := fun x j => (e j).symm (x j)
    commutes' := fun r => by
      ext i
      simp }
#align alg_equiv.Pi_congr_right AlgEquiv.piCongrRight

@[simp]
theorem piCongrRight_refl {R ι : Type _} {A : ι → Type _} [CommSemiring R] [∀ i, Semiring (A i)]
    [∀ i, Algebra R (A i)] :
    (piCongrRight fun i => (AlgEquiv.refl : A i ≃ₐ[R] A i)) = AlgEquiv.refl :=
  rfl
#align alg_equiv.Pi_congr_right_refl AlgEquiv.piCongrRight_refl

@[simp]
theorem piCongrRight_symm {R ι : Type _} {A₁ A₂ : ι → Type _} [CommSemiring R]
    [∀ i, Semiring (A₁ i)] [∀ i, Semiring (A₂ i)] [∀ i, Algebra R (A₁ i)] [∀ i, Algebra R (A₂ i)]
    (e : ∀ i, A₁ i ≃ₐ[R] A₂ i) : (piCongrRight e).symm = piCongrRight fun i => (e i).symm :=
  rfl
#align alg_equiv.Pi_congr_right_symm AlgEquiv.piCongrRight_symm

@[simp]
theorem piCongrRight_trans {R ι : Type _} {A₁ A₂ A₃ : ι → Type _} [CommSemiring R]
    [∀ i, Semiring (A₁ i)] [∀ i, Semiring (A₂ i)] [∀ i, Semiring (A₃ i)] [∀ i, Algebra R (A₁ i)]
    [∀ i, Algebra R (A₂ i)] [∀ i, Algebra R (A₃ i)] (e₁ : ∀ i, A₁ i ≃ₐ[R] A₂ i)
    (e₂ : ∀ i, A₂ i ≃ₐ[R] A₃ i) :
    (piCongrRight e₁).trans (piCongrRight e₂) = piCongrRight fun i => (e₁ i).trans (e₂ i) :=
  rfl
#align alg_equiv.Pi_congr_right_trans AlgEquiv.piCongrRight_trans

end AlgEquiv