{-# OPTIONS --type-in-type #-}

module Monoidal where

open import Base

-- ℂ
record IsParamMonoidalCategory
       {c : Set} {MonoidalProduct₀ : c × c  c} {Identity₀ :   c}
       ( : ParamCategory c)
       (MonoidalProduct : ParamFunctor (ParamProduct  )  MonoidalProduct₀)
       (funcI : ParamFunctor 𝟙  Identity₀) : Set where
  open ParamCategory 
  module MonoidalProduct = ParamFunctor MonoidalProduct
  module funcI = ParamFunctor funcI

  infixr 13 _⊗_
  infixr 13 _⊗₁_

  _⊗_ : c  c  c
  _⊗_ = λ x y  MonoidalProduct₀ (x , y)
  _⊗₁_ :  {X Y U V}  hom X Y  hom U V  hom (X  U) (Y  V)
  _⊗₁_ = λ x y  MonoidalProduct.F₁ (x , y)
  I = Identity₀ tt
  I₁ = funcI.F₁ tt
  field
    λ-at :  X  hom (I  X) X
    λ-naturality :  {A B} (f : hom A B)  I₁ ⊗₁ f  λ-at B  λ-at A  f
    ρ-at :  X  hom X (X  I)
    ρ-naturality :  {A B} (f : hom A B)  ρ-at A  f ⊗₁ I₁  f  ρ-at B
    α-at :  X Y Z  hom ((X  Y)  Z) (X  (Y  Z))
    α-naturality :  {A B C D E F} (f : hom A B) (g : hom C D) (h : hom E F)
                    (f ⊗₁ g) ⊗₁ h  α-at B D F  α-at A C E  f ⊗₁ (g ⊗₁ h) 
    triangle :  X Y  α-at X I Y  id X ⊗₁ λ-at Y  ρ-at X ⊗₁ (id Y)
                        id ((X  I)  Y)
    pentagon :  X Y Z W  α-at X Y Z ⊗₁ id W
                          α-at X (Y  Z) W
                          id X ⊗₁ α-at Y Z W
                          α-at (X  Y) Z W  α-at X Y (Z  W)


-- if it ends in Category, it exposes all the category stuff on the same level
record ParamMonoidalCategory
       (c : Set) (⊗₀ : c × c  c) (I₀ :   c) : Set where
  field
    P : ParamCategory c
  U = record { obj = c ; PC = P }
  open ParamCategory P
  field
    MonoidalProduct : ParamFunctor (ParamProduct P P) P ⊗₀
    funcI : ParamFunctor 𝟙 P I₀
    isParamMonoidalCategory : IsParamMonoidalCategory P MonoidalProduct funcI
  open ParamCategory P public
  open IsParamMonoidalCategory isParamMonoidalCategory public
  obj = c


record MonoidalCategory : Set where
  field
    c : Set
    MonoidalProduct₀ : c × c  c
    Identity₀ :   c
    P-monoidal : ParamMonoidalCategory c MonoidalProduct₀ Identity₀
  open ParamMonoidalCategory P-monoidal public

-- 𝕂
record IsParamMonoidalLikeCategory
       {c : Set} {MonoidalLikeProduct₀ : c × c  c} {Identity₀ :   c}
       ( : ParamCategory c)
       (MonoidalLikeProduct : ParamLaxFunctor (ParamProduct  )  MonoidalLikeProduct₀)
       (LikeI : ParamLaxFunctor 𝟙  Identity₀) : Set where
  open ParamCategory 
  module MonoidalLikeProduct = ParamLaxFunctor MonoidalLikeProduct
  module LikeI = ParamLaxFunctor LikeI

  infixr 13 _⊗_
  infixr 13 _∥_

  _⊗_ : c  c  c
  _⊗_ = λ x y  MonoidalLikeProduct₀ (x , y)
  _∥_ :  {X Y U V}  hom X Y  hom U V  hom (X  U) (Y  V)
  _∥_ = λ x y  MonoidalLikeProduct.F₁ (x , y)
  I = Identity₀ tt
  jd = LikeI.F₁ tt

record ParamMonoidalLikeCategory
       (c : Set) (⊗₀ : c × c  c) (I₀ :   c) : Set where
  field
    P : ParamCategory c
  U = record { obj = c ; PC = P }  
  open ParamCategory P
  field
    MonoidalLikeProduct : ParamLaxFunctor (ParamProduct P P) P ⊗₀
    funcLikeI : ParamLaxFunctor 𝟙 P I₀
    isParamMonoidalLikeCategory : IsParamMonoidalLikeCategory P MonoidalLikeProduct funcLikeI
  open ParamCategory P public
  open IsParamMonoidalLikeCategory isParamMonoidalLikeCategory public
  obj = c
  
record MonoidalLikeCategory : Set where
  field
    c : Set
    t⊗₀ : c × c  c
    tI₀ :   c
    P-monoidallike : ParamMonoidalLikeCategory c t⊗₀ tI₀
  open ParamMonoidalLikeCategory P-monoidallike public