module Proarrow.Category.Instance.PreorderAsCategory where

import Data.Kind (Constraint)

import Proarrow.Category.Monoidal (Monoidal (..), MonoidalProfunctor (..))
import Proarrow.Core (CAT, CategoryOf (..), Is, Profunctor, Promonad (..), UN, dimapDefault)
import Proarrow.Core qualified as Core
import Proarrow.Object.BinaryProduct (HasBinaryProducts (..))
import Proarrow.Object.BinaryProduct qualified as P
import Proarrow.Object.Terminal (HasTerminalObject (..))
import Proarrow.Preorder (CProfunctor (..), CPromonad (..), PreorderOf (..), (\\))
import Proarrow.Preorder.Constraint ()
import Proarrow.Preorder.ThinCategory (ThinProfunctor (..))
import Proarrow.Category.Dagger (DaggerProfunctor (..))
import Proarrow.Preorder.Discrete (DISCRETE)

newtype POCATK k = PC k
type instance UN PC (PC k) = k

data PoAsCat a b where
  PoAsCat :: (a <= b) => PoAsCat (PC a) (PC b)

instance (PreorderOf k) => Profunctor (PoAsCat :: CAT (POCATK k)) where
  dimap :: forall (c :: POCATK k) (a :: POCATK k) (b :: POCATK k)
       (d :: POCATK k).
(c ~> a) -> (b ~> d) -> PoAsCat a b -> PoAsCat c d
dimap = (c ~> a) -> (b ~> d) -> PoAsCat a b -> PoAsCat c d
PoAsCat c a -> PoAsCat b d -> PoAsCat a b -> PoAsCat c d
forall {k} (p :: PRO k k) (c :: k) (a :: k) (b :: k) (d :: k).
Promonad p =>
p c a -> p b d -> p a b -> p c d
dimapDefault
  (Ob a, Ob b) => r
r \\ :: forall (a :: POCATK k) (b :: POCATK k) r.
((Ob a, Ob b) => r) -> PoAsCat a b -> r
\\ PoAsCat @a @b = r
(COb a, COb b) => r
(Ob a, Ob b) => r
r ((COb a, COb b) => r) -> ((a <= b) :- (COb a, COb b)) -> r
forall (a :: Constraint) (c :: Constraint) r.
a =>
(c => r) -> (a :- c) -> r
\\ forall {k} (p :: k -> k -> Constraint) (a :: k) (b :: k).
CProfunctor p =>
p a b :- (COb a, COb b)
forall (p :: k -> k -> Constraint) (a :: k) (b :: k).
CProfunctor p =>
p a b :- (COb a, COb b)
obs @((<=) @k) @a @b
instance (PreorderOf k) => Promonad (PoAsCat :: CAT (POCATK k)) where
  id :: forall (a :: POCATK k). Ob a => PoAsCat a a
id @a = PoAsCat a a
PoAsCat ('PC (UN 'PC a)) ('PC (UN 'PC a))
(UN 'PC a <= UN 'PC a) => PoAsCat a a
forall {k} (a :: k) (b :: k). (a <= b) => PoAsCat ('PC a) ('PC b)
PoAsCat ((UN 'PC a <= UN 'PC a) => PoAsCat a a)
-> ((() :: Constraint) :- (UN 'PC a <= UN 'PC a)) -> PoAsCat a a
forall (a :: Constraint) (c :: Constraint) r.
a =>
(c => r) -> (a :- c) -> r
\\ forall {k} (p :: k -> k -> Constraint) (a :: k).
(CPromonad p, COb a) =>
(() :: Constraint) :- p a a
forall (p :: k -> k -> Constraint) (a :: k).
(CPromonad p, COb a) =>
(() :: Constraint) :- p a a
cid @((<=) @k) @(UN PC a)
  . :: forall (b :: POCATK k) (c :: POCATK k) (a :: POCATK k).
PoAsCat b c -> PoAsCat a b -> PoAsCat a c
(.) @b @c @a PoAsCat b c
PoAsCat PoAsCat a b
PoAsCat = PoAsCat a c
PoAsCat ('PC a) ('PC b)
(a <= b) => PoAsCat a c
forall {k} (a :: k) (b :: k). (a <= b) => PoAsCat ('PC a) ('PC b)
PoAsCat ((a <= b) => PoAsCat a c)
-> ((a <= b, a <= a) :- (a <= b)) -> PoAsCat a c
forall (a :: Constraint) (c :: Constraint) r.
a =>
(c => r) -> (a :- c) -> r
\\ forall {k} (p :: k -> k -> Constraint) (a :: k) (b :: k) (c :: k).
CPromonad p =>
(p b c, p a b) :- p a c
forall (p :: k -> k -> Constraint) (a :: k) (b :: k) (c :: k).
CPromonad p =>
(p b c, p a b) :- p a c
ccomp @((<=) @k) @(UN PC a) @(UN PC b) @(UN PC c)
instance (PreorderOf k) => CategoryOf (POCATK k) where
  type (~>) = PoAsCat
  type Ob a = (Is PC a, COb (UN PC a))

instance (PreorderOf k) => ThinProfunctor (PoAsCat :: CAT (POCATK k)) where
  type HasArrow PoAsCat (PC a) (PC b) = a <= b
  arr :: forall (a :: POCATK k) (b :: POCATK k).
(Ob a, Ob b, HasArrow PoAsCat a b) =>
PoAsCat a b
arr = PoAsCat a b
PoAsCat ('PC (UN 'PC a)) ('PC (UN 'PC b))
forall {k} (a :: k) (b :: k). (a <= b) => PoAsCat ('PC a) ('PC b)
PoAsCat
  withArr :: forall (a :: POCATK k) (b :: POCATK k) r.
PoAsCat a b -> (HasArrow PoAsCat a b => r) -> r
withArr PoAsCat a b
PoAsCat HasArrow PoAsCat a b => r
r = r
HasArrow PoAsCat a b => r
r

instance HasTerminalObject (POCATK Constraint) where
  type TerminalObject = PC (() :: Constraint)
  terminate' :: forall (a :: POCATK Constraint) (a' :: POCATK Constraint).
(a ~> a') -> a ~> TerminalObject
terminate' a ~> a'
PoAsCat a a'
PoAsCat = a ~> TerminalObject
PoAsCat ('PC a) ('PC (() :: Constraint))
forall {k} (a :: k) (b :: k). (a <= b) => PoAsCat ('PC a) ('PC b)
PoAsCat

instance HasBinaryProducts (POCATK Constraint) where
  type l && r = PC ((UN PC l, UN PC r) :: Constraint)
  fst' :: forall (a :: POCATK Constraint) (a' :: POCATK Constraint)
       (b :: POCATK Constraint).
(a ~> a') -> Obj b -> (a && b) ~> a'
fst' a ~> a'
PoAsCat a a'
PoAsCat Obj b
PoAsCat b b
PoAsCat = (a && b) ~> a'
PoAsCat ('PC (a, b)) ('PC b)
forall {k} (a :: k) (b :: k). (a <= b) => PoAsCat ('PC a) ('PC b)
PoAsCat
  snd' :: forall (a :: POCATK Constraint) (b :: POCATK Constraint)
       (b' :: POCATK Constraint).
Obj a -> (b ~> b') -> (a && b) ~> b'
snd' Obj a
PoAsCat a a
PoAsCat b ~> b'
PoAsCat b b'
PoAsCat = (a && b) ~> b'
PoAsCat ('PC (b, a)) ('PC b)
forall {k} (a :: k) (b :: k). (a <= b) => PoAsCat ('PC a) ('PC b)
PoAsCat
  a ~> x
PoAsCat a x
PoAsCat &&& :: forall (a :: POCATK Constraint) (x :: POCATK Constraint)
       (y :: POCATK Constraint).
(a ~> x) -> (a ~> y) -> a ~> (x && y)
&&& a ~> y
PoAsCat ('PC a) y
PoAsCat = a ~> (x && y)
PoAsCat ('PC a) ('PC (b, b))
forall {k} (a :: k) (b :: k). (a <= b) => PoAsCat ('PC a) ('PC b)
PoAsCat

instance MonoidalProfunctor (PoAsCat :: CAT (POCATK Constraint)) where
  par0 :: PoAsCat Unit Unit
par0 = PoAsCat Unit Unit
PoAsCat ('PC (() :: Constraint)) ('PC (() :: Constraint))
forall {k} (p :: PRO k k) (a :: k). (Promonad p, Ob a) => p a a
forall (a :: POCATK Constraint). Ob a => PoAsCat a a
id
  PoAsCat x1 x2
f par :: forall (x1 :: POCATK Constraint) (x2 :: POCATK Constraint)
       (y1 :: POCATK Constraint) (y2 :: POCATK Constraint).
PoAsCat x1 x2 -> PoAsCat y1 y2 -> PoAsCat (x1 ** y1) (x2 ** y2)
`par` PoAsCat y1 y2
g = x1 ~> x2
PoAsCat x1 x2
f (x1 ~> x2) -> (y1 ~> y2) -> (x1 && y1) ~> (x2 && y2)
forall k (a :: k) (b :: k) (x :: k) (y :: k).
HasBinaryProducts k =>
(a ~> x) -> (b ~> y) -> (a && b) ~> (x && y)
forall (a :: POCATK Constraint) (b :: POCATK Constraint)
       (x :: POCATK Constraint) (y :: POCATK Constraint).
(a ~> x) -> (b ~> y) -> (a && b) ~> (x && y)
*** y1 ~> y2
PoAsCat y1 y2
g

instance Monoidal (POCATK Constraint) where
  type Unit = TerminalObject
  type a ** b = a && b
  leftUnitor :: forall (a :: POCATK Constraint). Ob a => (Unit ** a) ~> a
leftUnitor = (Unit ** a) ~> a
(TerminalObject && 'PC (UN 'PC a)) ~> 'PC (UN 'PC a)
forall {k} (a :: k).
(HasProducts k, Ob a) =>
(TerminalObject && a) ~> a
P.leftUnitorProd
  leftUnitorInv :: forall (a :: POCATK Constraint). Ob a => a ~> (Unit ** a)
leftUnitorInv = a ~> (Unit ** a)
'PC (UN 'PC a) ~> (TerminalObject && 'PC (UN 'PC a))
forall {k} (a :: k).
(HasProducts k, Ob a) =>
a ~> (TerminalObject && a)
P.leftUnitorProdInv
  rightUnitor :: forall (a :: POCATK Constraint). Ob a => (a ** Unit) ~> a
rightUnitor = (a ** Unit) ~> a
('PC (UN 'PC a) && TerminalObject) ~> 'PC (UN 'PC a)
forall {k} (a :: k).
(HasProducts k, Ob a) =>
(a && TerminalObject) ~> a
P.rightUnitorProd
  rightUnitorInv :: forall (a :: POCATK Constraint). Ob a => a ~> (a ** Unit)
rightUnitorInv = a ~> (a ** Unit)
'PC (UN 'PC a) ~> ('PC (UN 'PC a) && TerminalObject)
forall {k} (a :: k).
(HasProducts k, Ob a) =>
a ~> (a && TerminalObject)
P.rightUnitorProdInv
  associator :: forall (a :: POCATK Constraint) (b :: POCATK Constraint)
       (c :: POCATK Constraint).
(Ob a, Ob b, Ob c) =>
((a ** b) ** c) ~> (a ** (b ** c))
associator = ((a ** b) ** c) ~> (a ** (b ** c))
(('PC (UN 'PC a) && 'PC (UN 'PC b)) && 'PC (UN 'PC c))
~> ('PC (UN 'PC a) && ('PC (UN 'PC b) && 'PC (UN 'PC c)))
forall {k} (a :: k) (b :: k) (c :: k).
(HasProducts k, Ob a, Ob b, Ob c) =>
((a && b) && c) ~> (a && (b && c))
P.associatorProd
  associatorInv :: forall (a :: POCATK Constraint) (b :: POCATK Constraint)
       (c :: POCATK Constraint).
(Ob a, Ob b, Ob c) =>
(a ** (b ** c)) ~> ((a ** b) ** c)
associatorInv = (a ** (b ** c)) ~> ((a ** b) ** c)
('PC (UN 'PC a) && ('PC (UN 'PC b) && 'PC (UN 'PC c)))
~> (('PC (UN 'PC a) && 'PC (UN 'PC b)) && 'PC (UN 'PC c))
forall {k} (a :: k) (b :: k) (c :: k).
(HasProducts k, Ob a, Ob b, Ob c) =>
(a && (b && c)) ~> ((a && b) && c)
P.associatorProdInv

instance DaggerProfunctor (PoAsCat :: CAT (POCATK (DISCRETE k))) where
  dagger :: forall (a :: POCATK (DISCRETE k)) (b :: POCATK (DISCRETE k)).
PoAsCat a b -> PoAsCat b a
dagger PoAsCat a b
PoAsCat = PoAsCat b a
PoAsCat ('PC b) ('PC b)
forall {k} (a :: k) (b :: k). (a <= b) => PoAsCat ('PC a) ('PC b)
PoAsCat