{-# LANGUAGE AllowAmbiguousTypes #-}

module Proarrow.Object.Exponential where

import Data.Kind (Type)
import Prelude qualified as P

import Proarrow.Category.Instance.Product ((:**:) (..))
import Proarrow.Category.Instance.Prof (Prof (..))
import Proarrow.Category.Instance.Unit qualified as U
import Proarrow.Category.Monoidal (Monoidal (..), MonoidalProfunctor (..), associator, leftUnitor)
import Proarrow.Category.Opposite (OPPOSITE (..), Op (..))
import Proarrow.Core (CategoryOf (..), PRO, Profunctor (..), Promonad (..), UN, tgt, (//))
import Proarrow.Object (Obj, obj)
import Proarrow.Object.BinaryCoproduct (HasCoproducts)
import Proarrow.Object.BinaryProduct (Cartesian, PROD (..), Prod (..), diag)
import Proarrow.Profunctor.Exponential ((:~>:) (..))
import Proarrow.Profunctor.Product ((:*:) (..))
import Proarrow.Profunctor.Representable (Representable (..), dimapRep)

infixr 2 ~~>

class (Monoidal k) => Closed k where
  type (a :: k) ~~> (b :: k) :: k
  curry' :: Obj (a :: k) -> Obj b -> a ** b ~> c -> a ~> b ~~> c
  uncurry' :: Obj (b :: k) -> Obj c -> a ~> b ~~> c -> a ** b ~> c
  (^^^) :: (b :: k) ~> y -> x ~> a -> a ~~> b ~> x ~~> y

curry :: forall {k} (a :: k) b c. (Closed k, Ob a, Ob b) => a ** b ~> c -> a ~> b ~~> c
curry :: forall {k} (a :: k) (b :: k) (c :: k).
(Closed k, Ob a, Ob b) =>
((a ** b) ~> c) -> a ~> (b ~~> c)
curry = Obj a -> Obj b -> ((a ** b) ~> c) -> a ~> (b ~~> c)
forall (a :: k) (b :: k) (c :: k).
Obj a -> Obj b -> ((a ** b) ~> c) -> a ~> (b ~~> c)
forall k (a :: k) (b :: k) (c :: k).
Closed k =>
Obj a -> Obj b -> ((a ** b) ~> c) -> a ~> (b ~~> c)
curry' (forall (a :: k). (CategoryOf k, Ob a) => Obj a
forall {k} (a :: k). (CategoryOf k, Ob a) => Obj a
obj @a) (forall (a :: k). (CategoryOf k, Ob a) => Obj a
forall {k} (a :: k). (CategoryOf k, Ob a) => Obj a
obj @b)

uncurry :: forall {k} (a :: k) b c. (Closed k, Ob b, Ob c) => a ~> b ~~> c -> a ** b ~> c
uncurry :: forall {k} (a :: k) (b :: k) (c :: k).
(Closed k, Ob b, Ob c) =>
(a ~> (b ~~> c)) -> (a ** b) ~> c
uncurry = Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
forall (b :: k) (c :: k) (a :: k).
Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
forall k (b :: k) (c :: k) (a :: k).
Closed k =>
Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
uncurry' (forall (a :: k). (CategoryOf k, Ob a) => Obj a
forall {k} (a :: k). (CategoryOf k, Ob a) => Obj a
obj @b) (forall (a :: k). (CategoryOf k, Ob a) => Obj a
forall {k} (a :: k). (CategoryOf k, Ob a) => Obj a
obj @c)

comp :: forall {k} (a :: k) b c. (Closed k, Ob a, Ob b, Ob c) => (b ~~> c) ** (a ~~> b) ~> a ~~> c
comp :: forall {k} (a :: k) (b :: k) (c :: k).
(Closed k, Ob a, Ob b, Ob c) =>
((b ~~> c) ** (a ~~> b)) ~> (a ~~> c)
comp =
  let a :: Obj a
a = forall (a :: k). (CategoryOf k, Ob a) => Obj a
forall {k} (a :: k). (CategoryOf k, Ob a) => Obj a
obj @a; b :: Obj b
b = forall (a :: k). (CategoryOf k, Ob a) => Obj a
forall {k} (a :: k). (CategoryOf k, Ob a) => Obj a
obj @b; b2c :: (b ~~> c) ~> (b ~~> c)
b2c = forall (a :: k). (CategoryOf k, Ob a) => Obj a
forall {k} (a :: k). (CategoryOf k, Ob a) => Obj a
obj @c Obj c -> Obj b -> (b ~~> c) ~> (b ~~> c)
forall (b :: k) (y :: k) (x :: k) (a :: k).
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
forall k (b :: k) (y :: k) (x :: k) (a :: k).
Closed k =>
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
^^^ Obj b
b; a2b :: (a ~~> b) ~> (a ~~> b)
a2b = Obj b
b Obj b -> Obj a -> (a ~~> b) ~> (a ~~> b)
forall (b :: k) (y :: k) (x :: k) (a :: k).
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
forall k (b :: k) (y :: k) (x :: k) (a :: k).
Closed k =>
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
^^^ Obj a
a
  in forall (a :: k) (b :: k) (c :: k).
(Closed k, Ob a, Ob b) =>
((a ** b) ~> c) -> a ~> (b ~~> c)
forall {k} (a :: k) (b :: k) (c :: k).
(Closed k, Ob a, Ob b) =>
((a ** b) ~> c) -> a ~> (b ~~> c)
curry @_ @a @c (forall (a :: k) (b :: k).
(Closed k, Ob a, Ob b) =>
((a ~~> b) ** a) ~> b
forall {k} (a :: k) (b :: k).
(Closed k, Ob a, Ob b) =>
((a ~~> b) ** a) ~> b
eval @b @c (((b ~~> c) ** b) ~> c)
-> ((((b ~~> c) ** (a ~~> b)) ** a) ~> ((b ~~> c) ** b))
-> (((b ~~> c) ** (a ~~> b)) ** a) ~> c
forall (b :: k) (c :: k) (a :: k). (b ~> c) -> (a ~> b) -> a ~> c
forall {k} (p :: PRO k k) (b :: k) (c :: k) (a :: k).
Promonad p =>
p b c -> p a b -> p a c
. ((b ~~> c) ~> (b ~~> c)
b2c ((b ~~> c) ~> (b ~~> c))
-> (((a ~~> b) ** a) ~> b)
-> ((b ~~> c) ** ((a ~~> b) ** a)) ~> ((b ~~> c) ** b)
forall (x1 :: k) (x2 :: k) (y1 :: k) (y2 :: k).
(x1 ~> x2) -> (y1 ~> y2) -> (x1 ** y1) ~> (x2 ** y2)
forall {j} {k} (p :: j +-> k) (x1 :: k) (x2 :: j) (y1 :: k)
       (y2 :: j).
MonoidalProfunctor p =>
p x1 x2 -> p y1 y2 -> p (x1 ** y1) (x2 ** y2)
`par` forall (a :: k) (b :: k).
(Closed k, Ob a, Ob b) =>
((a ~~> b) ** a) ~> b
forall {k} (a :: k) (b :: k).
(Closed k, Ob a, Ob b) =>
((a ~~> b) ** a) ~> b
eval @a @b) (((b ~~> c) ** ((a ~~> b) ** a)) ~> ((b ~~> c) ** b))
-> ((((b ~~> c) ** (a ~~> b)) ** a)
    ~> ((b ~~> c) ** ((a ~~> b) ** a)))
-> (((b ~~> c) ** (a ~~> b)) ** a) ~> ((b ~~> c) ** b)
forall (b :: k) (c :: k) (a :: k). (b ~> c) -> (a ~> b) -> a ~> c
forall {k} (p :: PRO k k) (b :: k) (c :: k) (a :: k).
Promonad p =>
p b c -> p a b -> p a c
. forall k (a :: k) (b :: k) (c :: k).
(Monoidal k, Ob a, Ob b, Ob c) =>
((a ** b) ** c) ~> (a ** (b ** c))
associator @k @(b ~~> c) @(a ~~> b) @a)
      ((Ob (a ~~> b), Ob (a ~~> b)) =>
 ((b ~~> c) ** (a ~~> b)) ~> (a ~~> c))
-> ((a ~~> b) ~> (a ~~> b))
-> ((b ~~> c) ** (a ~~> b)) ~> (a ~~> c)
forall (a :: k) (b :: k) r. ((Ob a, Ob b) => r) -> (a ~> b) -> r
forall {j} {k} (p :: PRO j k) (a :: j) (b :: k) r.
Profunctor p =>
((Ob a, Ob b) => r) -> p a b -> r
\\ (a ~~> b) ~> (a ~~> b)
a2b
      ((Ob (b ~~> c), Ob (b ~~> c)) =>
 ((b ~~> c) ** (a ~~> b)) ~> (a ~~> c))
-> ((b ~~> c) ~> (b ~~> c))
-> ((b ~~> c) ** (a ~~> b)) ~> (a ~~> c)
forall (a :: k) (b :: k) r. ((Ob a, Ob b) => r) -> (a ~> b) -> r
forall {j} {k} (p :: PRO j k) (a :: j) (b :: k) r.
Profunctor p =>
((Ob a, Ob b) => r) -> p a b -> r
\\ (b ~~> c) ~> (b ~~> c)
b2c
      ((Ob ((b ~~> c) ** (a ~~> b)), Ob ((b ~~> c) ** (a ~~> b))) =>
 ((b ~~> c) ** (a ~~> b)) ~> (a ~~> c))
-> (((b ~~> c) ** (a ~~> b)) ~> ((b ~~> c) ** (a ~~> b)))
-> ((b ~~> c) ** (a ~~> b)) ~> (a ~~> c)
forall (a :: k) (b :: k) r. ((Ob a, Ob b) => r) -> (a ~> b) -> r
forall {j} {k} (p :: PRO j k) (a :: j) (b :: k) r.
Profunctor p =>
((Ob a, Ob b) => r) -> p a b -> r
\\ ((b ~~> c) ~> (b ~~> c)
b2c ((b ~~> c) ~> (b ~~> c))
-> ((a ~~> b) ~> (a ~~> b))
-> ((b ~~> c) ** (a ~~> b)) ~> ((b ~~> c) ** (a ~~> b))
forall (x1 :: k) (x2 :: k) (y1 :: k) (y2 :: k).
(x1 ~> x2) -> (y1 ~> y2) -> (x1 ** y1) ~> (x2 ** y2)
forall {j} {k} (p :: j +-> k) (x1 :: k) (x2 :: j) (y1 :: k)
       (y2 :: j).
MonoidalProfunctor p =>
p x1 x2 -> p y1 y2 -> p (x1 ** y1) (x2 ** y2)
`par` (a ~~> b) ~> (a ~~> b)
a2b)

mkExponential :: forall {k} a b. (Closed k) => (a :: k) ~> b -> Unit ~> (a ~~> b)
mkExponential :: forall {k} (a :: k) (b :: k).
Closed k =>
(a ~> b) -> Unit ~> (a ~~> b)
mkExponential a ~> b
ab = forall (a :: k) (b :: k) (c :: k).
(Closed k, Ob a, Ob b) =>
((a ** b) ~> c) -> a ~> (b ~~> c)
forall {k} (a :: k) (b :: k) (c :: k).
(Closed k, Ob a, Ob b) =>
((a ** b) ~> c) -> a ~> (b ~~> c)
curry @_ @a (a ~> b
ab (a ~> b) -> ((Unit ** a) ~> a) -> (Unit ** a) ~> b
forall (b :: k) (c :: k) (a :: k). (b ~> c) -> (a ~> b) -> a ~> c
forall {k} (p :: PRO k k) (b :: k) (c :: k) (a :: k).
Promonad p =>
p b c -> p a b -> p a c
. (Unit ** a) ~> a
forall (a :: k). Ob a => (Unit ** a) ~> a
forall k (a :: k). (Monoidal k, Ob a) => (Unit ** a) ~> a
leftUnitor) ((Ob a, Ob b) => Unit ~> (a ~~> b))
-> (a ~> b) -> Unit ~> (a ~~> b)
forall (a :: k) (b :: k) r. ((Ob a, Ob b) => r) -> (a ~> b) -> r
forall {j} {k} (p :: PRO j k) (a :: j) (b :: k) r.
Profunctor p =>
((Ob a, Ob b) => r) -> p a b -> r
\\ a ~> b
ab ((Ob Unit, Ob Unit) => Unit ~> (a ~~> b))
-> (Unit ~> Unit) -> Unit ~> (a ~~> b)
forall (a :: k) (b :: k) r. ((Ob a, Ob b) => r) -> (a ~> b) -> r
forall {j} {k} (p :: PRO j k) (a :: j) (b :: k) r.
Profunctor p =>
((Ob a, Ob b) => r) -> p a b -> r
\\ (Unit ~> Unit
forall {j} {k} (p :: j +-> k). MonoidalProfunctor p => p Unit Unit
par0 :: (Unit :: k) ~> Unit)

lower :: forall {k} (a :: k) b. (Closed k, Ob a, Ob b) => (Unit ~> (a ~~> b)) -> a ~> b
lower :: forall {k} (a :: k) (b :: k).
(Closed k, Ob a, Ob b) =>
(Unit ~> (a ~~> b)) -> a ~> b
lower Unit ~> (a ~~> b)
f = forall (a :: k) (b :: k) (c :: k).
(Closed k, Ob b, Ob c) =>
(a ~> (b ~~> c)) -> (a ** b) ~> c
forall {k} (a :: k) (b :: k) (c :: k).
(Closed k, Ob b, Ob c) =>
(a ~> (b ~~> c)) -> (a ** b) ~> c
uncurry @Unit @a @b Unit ~> (a ~~> b)
f ((Unit ** a) ~> b) -> (a ~> (Unit ** a)) -> a ~> b
forall (b :: k) (c :: k) (a :: k). (b ~> c) -> (a ~> b) -> a ~> c
forall {k} (p :: PRO k k) (b :: k) (c :: k) (a :: k).
Promonad p =>
p b c -> p a b -> p a c
. a ~> (Unit ** a)
forall (a :: k). Ob a => a ~> (Unit ** a)
forall k (a :: k). (Monoidal k, Ob a) => a ~> (Unit ** a)
leftUnitorInv

eval' :: (Closed k) => a ~> a' -> b ~> b' -> ((a' :: k) ~~> b) ** a ~> b'
eval' :: forall k (a :: k) (a' :: k) (b :: k) (b' :: k).
Closed k =>
(a ~> a') -> (b ~> b') -> ((a' ~~> b) ** a) ~> b'
eval' a ~> a'
a b ~> b'
b = let ab :: (a' ~~> b) ~> (a' ~~> b')
ab = b ~> b'
b (b ~> b') -> (a' ~> a') -> (a' ~~> b) ~> (a' ~~> b')
forall (b :: k) (y :: k) (x :: k) (a :: k).
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
forall k (b :: k) (y :: k) (x :: k) (a :: k).
Closed k =>
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
^^^ (a ~> a') -> a' ~> a'
forall {k1} {k2} (a :: k2) (b :: k1) (p :: PRO k2 k1).
Profunctor p =>
p a b -> Obj b
tgt a ~> a'
a in (a' ~> a')
-> Obj b'
-> ((a' ~~> b') ~> (a' ~~> b'))
-> ((a' ~~> b') ** a') ~> b'
forall (b :: k) (c :: k) (a :: k).
Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
forall k (b :: k) (c :: k) (a :: k).
Closed k =>
Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
uncurry' ((a ~> a') -> a' ~> a'
forall {k1} {k2} (a :: k2) (b :: k1) (p :: PRO k2 k1).
Profunctor p =>
p a b -> Obj b
tgt a ~> a'
a) ((b ~> b') -> Obj b'
forall {k1} {k2} (a :: k2) (b :: k1) (p :: PRO k2 k1).
Profunctor p =>
p a b -> Obj b
tgt b ~> b'
b) (((a' ~~> b) ~> (a' ~~> b')) -> (a' ~~> b') ~> (a' ~~> b')
forall {k1} {k2} (a :: k2) (b :: k1) (p :: PRO k2 k1).
Profunctor p =>
p a b -> Obj b
tgt (a' ~~> b) ~> (a' ~~> b')
ab) (((a' ~~> b') ** a') ~> b')
-> (((a' ~~> b) ** a) ~> ((a' ~~> b') ** a'))
-> ((a' ~~> b) ** a) ~> b'
forall (b :: k) (c :: k) (a :: k). (b ~> c) -> (a ~> b) -> a ~> c
forall {k} (p :: PRO k k) (b :: k) (c :: k) (a :: k).
Promonad p =>
p b c -> p a b -> p a c
. ((a' ~~> b) ~> (a' ~~> b')
ab ((a' ~~> b) ~> (a' ~~> b'))
-> (a ~> a') -> ((a' ~~> b) ** a) ~> ((a' ~~> b') ** a')
forall (x1 :: k) (x2 :: k) (y1 :: k) (y2 :: k).
(x1 ~> x2) -> (y1 ~> y2) -> (x1 ** y1) ~> (x2 ** y2)
forall {j} {k} (p :: j +-> k) (x1 :: k) (x2 :: j) (y1 :: k)
       (y2 :: j).
MonoidalProfunctor p =>
p x1 x2 -> p y1 y2 -> p (x1 ** y1) (x2 ** y2)
`par` a ~> a'
a)

eval :: forall {k} a b. (Closed k, Ob a, Ob b) => ((a :: k) ~~> b) ** a ~> b
eval :: forall {k} (a :: k) (b :: k).
(Closed k, Ob a, Ob b) =>
((a ~~> b) ** a) ~> b
eval = (a ~> a) -> (b ~> b) -> ((a ~~> b) ** a) ~> b
forall k (a :: k) (a' :: k) (b :: k) (b' :: k).
Closed k =>
(a ~> a') -> (b ~> b') -> ((a' ~~> b) ** a) ~> b'
eval' (forall (a :: k). (CategoryOf k, Ob a) => Obj a
forall {k} (a :: k). (CategoryOf k, Ob a) => Obj a
obj @a) (forall (a :: k). (CategoryOf k, Ob a) => Obj a
forall {k} (a :: k). (CategoryOf k, Ob a) => Obj a
obj @b)

instance Closed Type where
  type a ~~> b = a -> b
  curry' :: forall a b c. Obj a -> Obj b -> ((a ** b) ~> c) -> a ~> (b ~~> c)
curry' Obj a
_ Obj b
_ = ((a ** b) ~> c) -> a ~> (b ~~> c)
((a, b) -> c) -> a -> b -> c
forall a b c. ((a, b) -> c) -> a -> b -> c
P.curry
  uncurry' :: forall b c a. Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
uncurry' Obj b
_ Obj c
_ = (a ~> (b ~~> c)) -> (a ** b) ~> c
(a -> b -> c) -> (a, b) -> c
forall a b c. (a -> b -> c) -> (a, b) -> c
P.uncurry
  ^^^ :: forall b y x a. (b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
(^^^) = ((x -> a) -> (b -> y) -> (a -> b) -> x -> y)
-> (b -> y) -> (x -> a) -> (a -> b) -> x -> y
forall a b c. (a -> b -> c) -> b -> a -> c
P.flip (x ~> a) -> (b ~> y) -> (a -> b) -> x -> y
(x -> a) -> (b -> y) -> (a -> b) -> x -> y
forall c a b d. (c ~> a) -> (b ~> d) -> (a -> b) -> c -> d
forall {j} {k} (p :: PRO j k) (c :: j) (a :: j) (b :: k) (d :: k).
Profunctor p =>
(c ~> a) -> (b ~> d) -> p a b -> p c d
dimap

instance Closed () where
  type '() ~~> '() = '()
  curry' :: forall (a :: ()) (b :: ()) (c :: ()).
Obj a -> Obj b -> ((a ** b) ~> c) -> a ~> (b ~~> c)
curry' Obj a
Unit a a
U.Unit Obj b
Unit b b
U.Unit (a ** b) ~> c
Unit '() c
U.Unit = a ~> (b ~~> c)
Unit '() '()
U.Unit
  uncurry' :: forall (b :: ()) (c :: ()) (a :: ()).
Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
uncurry' Obj b
Unit b b
U.Unit Obj c
Unit c c
U.Unit a ~> (b ~~> c)
Unit a '()
U.Unit = (a ** b) ~> c
Unit '() '()
U.Unit
  b ~> y
Unit b y
U.Unit ^^^ :: forall (b :: ()) (y :: ()) (x :: ()) (a :: ()).
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
^^^ x ~> a
Unit x a
U.Unit = (a ~~> b) ~> (x ~~> y)
Unit '() '()
U.Unit

instance (CategoryOf j, CategoryOf k) => Closed (PROD (PRO j k)) where
  type p ~~> q = PR (UN PR p :~>: UN PR q)
  curry' :: forall (a :: PROD (PRO j k)) (b :: PROD (PRO j k))
       (c :: PROD (PRO j k)).
Obj a -> Obj b -> ((a ** b) ~> c) -> a ~> (b ~~> c)
curry' (Prod Prof{}) (Prod Prof{}) (Prod (Prof (b1 :*: b1) :~> b1
n)) = Prof b1 (b1 :~>: b1) -> Prod Prof ('PR b1) ('PR (b1 :~>: b1))
forall {j} {k} (p :: j +-> k) (a1 :: k) (b1 :: j).
p a1 b1 -> Prod p ('PR a1) ('PR b1)
Prod ((b1 :~> (b1 :~>: b1)) -> Prof b1 (b1 :~>: b1)
forall {k} {j} (p :: j +-> k) (q :: j +-> k).
(Profunctor p, Profunctor q) =>
(p :~> q) -> Prof p q
Prof \b1 a b
p -> b1 a b
p b1 a b -> ((Ob a, Ob b) => (:~>:) b1 b1 a b) -> (:~>:) b1 b1 a b
forall {k1} {k2} (p :: PRO k1 k2) (a :: k1) (b :: k2) r.
Profunctor p =>
p a b -> ((Ob a, Ob b) => r) -> r
// (forall (c :: j) (d :: k).
 (c ~> a) -> (b ~> d) -> b1 c d -> b1 c d)
-> (:~>:) b1 b1 a b
forall {k} {k1} (a :: k) (b :: k1) (p :: k -> k1 -> Type)
       (q :: k -> k1 -> Type).
(Ob a, Ob b) =>
(forall (c :: k) (d :: k1). (c ~> a) -> (b ~> d) -> p c d -> q c d)
-> (:~>:) p q a b
Exp \c ~> a
ca b ~> d
bd b1 c d
q -> (:*:) b1 b1 c d -> b1 c d
(b1 :*: b1) :~> b1
n ((c ~> a) -> (b ~> d) -> b1 a b -> b1 c d
forall (c :: j) (a :: j) (b :: k) (d :: k).
(c ~> a) -> (b ~> d) -> b1 a b -> b1 c d
forall {j} {k} (p :: PRO j k) (c :: j) (a :: j) (b :: k) (d :: k).
Profunctor p =>
(c ~> a) -> (b ~> d) -> p a b -> p c d
dimap c ~> a
ca b ~> d
bd b1 a b
p b1 c d -> b1 c d -> (:*:) b1 b1 c d
forall {j} {k} (p :: PRO j k) (a :: j) (b :: k) (q :: PRO j k).
p a b -> q a b -> (:*:) p q a b
:*: b1 c d
q))
  uncurry' :: forall (b :: PROD (PRO j k)) (c :: PROD (PRO j k))
       (a :: PROD (PRO j k)).
Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
uncurry' (Prod Prof{}) (Prod Prof{}) (Prod (Prof a1 :~> (b1 :~>: b1)
n)) = Prof (a1 :*: b1) b1 -> Prod Prof ('PR (a1 :*: b1)) ('PR b1)
forall {j} {k} (p :: j +-> k) (a1 :: k) (b1 :: j).
p a1 b1 -> Prod p ('PR a1) ('PR b1)
Prod (((a1 :*: b1) :~> b1) -> Prof (a1 :*: b1) b1
forall {k} {j} (p :: j +-> k) (q :: j +-> k).
(Profunctor p, Profunctor q) =>
(p :~> q) -> Prof p q
Prof \(a1 a b
p :*: b1 a b
q) -> case a1 a b -> (:~>:) b1 b1 a b
a1 :~> (b1 :~>: b1)
n a1 a b
p of Exp forall (c :: j) (d :: k). (c ~> a) -> (b ~> d) -> b1 c d -> b1 c d
f -> (a ~> a) -> (b ~> b) -> b1 a b -> b1 a b
forall (c :: j) (d :: k). (c ~> a) -> (b ~> d) -> b1 c d -> b1 c d
f a ~> a
forall (a :: j). Ob a => a ~> a
forall {k} (p :: PRO k k) (a :: k). (Promonad p, Ob a) => p a a
id b ~> b
forall (a :: k). Ob a => a ~> a
forall {k} (p :: PRO k k) (a :: k). (Promonad p, Ob a) => p a a
id b1 a b
q ((Ob a, Ob b) => b1 a b) -> b1 a b -> b1 a b
forall (a :: j) (b :: k) r. ((Ob a, Ob b) => r) -> b1 a b -> r
forall {j} {k} (p :: PRO j k) (a :: j) (b :: k) r.
Profunctor p =>
((Ob a, Ob b) => r) -> p a b -> r
\\ b1 a b
q)
  Prod (Prof a1 :~> b1
m) ^^^ :: forall (b :: PROD (PRO j k)) (y :: PROD (PRO j k))
       (x :: PROD (PRO j k)) (a :: PROD (PRO j k)).
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
^^^ Prod (Prof a1 :~> b1
n) = Prof (b1 :~>: a1) (a1 :~>: b1)
-> Prod Prof ('PR (b1 :~>: a1)) ('PR (a1 :~>: b1))
forall {j} {k} (p :: j +-> k) (a1 :: k) (b1 :: j).
p a1 b1 -> Prod p ('PR a1) ('PR b1)
Prod (((b1 :~>: a1) :~> (a1 :~>: b1)) -> Prof (b1 :~>: a1) (a1 :~>: b1)
forall {k} {j} (p :: j +-> k) (q :: j +-> k).
(Profunctor p, Profunctor q) =>
(p :~> q) -> Prof p q
Prof \(Exp forall (c :: j) (d :: k). (c ~> a) -> (b ~> d) -> b1 c d -> a1 c d
f) -> (forall (c :: j) (d :: k).
 (c ~> a) -> (b ~> d) -> a1 c d -> b1 c d)
-> (:~>:) a1 b1 a b
forall {k} {k1} (a :: k) (b :: k1) (p :: k -> k1 -> Type)
       (q :: k -> k1 -> Type).
(Ob a, Ob b) =>
(forall (c :: k) (d :: k1). (c ~> a) -> (b ~> d) -> p c d -> q c d)
-> (:~>:) p q a b
Exp \c ~> a
ca b ~> d
bd a1 c d
p -> a1 c d -> b1 c d
a1 :~> b1
m ((c ~> a) -> (b ~> d) -> b1 c d -> a1 c d
forall (c :: j) (d :: k). (c ~> a) -> (b ~> d) -> b1 c d -> a1 c d
f c ~> a
ca b ~> d
bd (a1 c d -> b1 c d
a1 :~> b1
n a1 c d
p)))

instance (Closed j, Closed k) => Closed (j, k) where
  type '(a1, a2) ~~> '(b1, b2) = '(a1 ~~> b1, a2 ~~> b2)
  curry' :: forall (a :: (j, k)) (b :: (j, k)) (c :: (j, k)).
Obj a -> Obj b -> ((a ** b) ~> c) -> a ~> (b ~~> c)
curry' (a1 ~> b1
a1 :**: a2 ~> b2
a2) (a1 ~> b1
b1 :**: a2 ~> b2
b2) (a1 ~> b1
f1 :**: a2 ~> b2
f2) = Obj b1 -> Obj b1 -> ((b1 ** b1) ~> b1) -> b1 ~> (b1 ~~> b1)
forall (a :: j) (b :: j) (c :: j).
Obj a -> Obj b -> ((a ** b) ~> c) -> a ~> (b ~~> c)
forall k (a :: k) (b :: k) (c :: k).
Closed k =>
Obj a -> Obj b -> ((a ** b) ~> c) -> a ~> (b ~~> c)
curry' a1 ~> b1
Obj b1
a1 a1 ~> b1
Obj b1
b1 a1 ~> b1
(b1 ** b1) ~> b1
f1 (b1 ~> (b1 ~~> b1))
-> (b2 ~> (b2 ~~> b2))
-> (:**:) (~>) (~>) '(b1, b2) '(b1 ~~> b1, b2 ~~> b2)
forall {j1} {k1} {j2} {k2} (c :: j1 +-> k1) (a1 :: k1) (b1 :: j1)
       (d :: j2 +-> k2) (a2 :: k2) (b2 :: j2).
c a1 b1 -> d a2 b2 -> (:**:) c d '(a1, a2) '(b1, b2)
:**: Obj b2 -> Obj b2 -> ((b2 ** b2) ~> b2) -> b2 ~> (b2 ~~> b2)
forall (a :: k) (b :: k) (c :: k).
Obj a -> Obj b -> ((a ** b) ~> c) -> a ~> (b ~~> c)
forall k (a :: k) (b :: k) (c :: k).
Closed k =>
Obj a -> Obj b -> ((a ** b) ~> c) -> a ~> (b ~~> c)
curry' a2 ~> b2
Obj b2
a2 a2 ~> b2
Obj b2
b2 a2 ~> b2
(b2 ** b2) ~> b2
f2
  uncurry' :: forall (b :: (j, k)) (c :: (j, k)) (a :: (j, k)).
Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
uncurry' (a1 ~> b1
a1 :**: a2 ~> b2
a2) (a1 ~> b1
b1 :**: a2 ~> b2
b2) (a1 ~> b1
f1 :**: a2 ~> b2
f2) = Obj b1 -> Obj b1 -> (a1 ~> (b1 ~~> b1)) -> (a1 ** b1) ~> b1
forall (b :: j) (c :: j) (a :: j).
Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
forall k (b :: k) (c :: k) (a :: k).
Closed k =>
Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
uncurry' a1 ~> b1
Obj b1
a1 a1 ~> b1
Obj b1
b1 a1 ~> b1
a1 ~> (b1 ~~> b1)
f1 ((a1 ** b1) ~> b1)
-> ((a2 ** b2) ~> b2)
-> (:**:) (~>) (~>) '(a1 ** b1, a2 ** b2) '(b1, b2)
forall {j1} {k1} {j2} {k2} (c :: j1 +-> k1) (a1 :: k1) (b1 :: j1)
       (d :: j2 +-> k2) (a2 :: k2) (b2 :: j2).
c a1 b1 -> d a2 b2 -> (:**:) c d '(a1, a2) '(b1, b2)
:**: Obj b2 -> Obj b2 -> (a2 ~> (b2 ~~> b2)) -> (a2 ** b2) ~> b2
forall (b :: k) (c :: k) (a :: k).
Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
forall k (b :: k) (c :: k) (a :: k).
Closed k =>
Obj b -> Obj c -> (a ~> (b ~~> c)) -> (a ** b) ~> c
uncurry' a2 ~> b2
Obj b2
a2 a2 ~> b2
Obj b2
b2 a2 ~> b2
a2 ~> (b2 ~~> b2)
f2
  (a1 ~> b1
f1 :**: a2 ~> b2
f2) ^^^ :: forall (b :: (j, k)) (y :: (j, k)) (x :: (j, k)) (a :: (j, k)).
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
^^^ (a1 ~> b1
g1 :**: a2 ~> b2
g2) = (a1 ~> b1
f1 (a1 ~> b1) -> (a1 ~> b1) -> (b1 ~~> a1) ~> (a1 ~~> b1)
forall (b :: j) (y :: j) (x :: j) (a :: j).
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
forall k (b :: k) (y :: k) (x :: k) (a :: k).
Closed k =>
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
^^^ a1 ~> b1
g1) ((b1 ~~> a1) ~> (a1 ~~> b1))
-> ((b2 ~~> a2) ~> (a2 ~~> b2))
-> (:**:) (~>) (~>) '(b1 ~~> a1, b2 ~~> a2) '(a1 ~~> b1, a2 ~~> b2)
forall {j1} {k1} {j2} {k2} (c :: j1 +-> k1) (a1 :: k1) (b1 :: j1)
       (d :: j2 +-> k2) (a2 :: k2) (b2 :: j2).
c a1 b1 -> d a2 b2 -> (:**:) c d '(a1, a2) '(b1, b2)
:**: (a2 ~> b2
f2 (a2 ~> b2) -> (a2 ~> b2) -> (b2 ~~> a2) ~> (a2 ~~> b2)
forall (b :: k) (y :: k) (x :: k) (a :: k).
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
forall k (b :: k) (y :: k) (x :: k) (a :: k).
Closed k =>
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
^^^ a2 ~> b2
g2)

type ExponentialFunctor :: PRO k (OPPOSITE k, k)
data ExponentialFunctor a b where
  ExponentialFunctor :: (Ob c, Ob d) => a ~> (c ~~> d) -> ExponentialFunctor a '(OP c, d)

instance (Closed k) => Profunctor (ExponentialFunctor :: PRO k (OPPOSITE k, k)) where
  dimap :: forall (c :: k) (a :: k) (b :: (OPPOSITE k, k))
       (d :: (OPPOSITE k, k)).
(c ~> a)
-> (b ~> d) -> ExponentialFunctor a b -> ExponentialFunctor c d
dimap = (c ~> a)
-> (b ~> d) -> ExponentialFunctor a b -> ExponentialFunctor c d
forall {j} {k} (p :: j +-> k) (a :: k) (b :: j) (c :: k) (d :: j).
Representable p =>
(c ~> a) -> (b ~> d) -> p a b -> p c d
dimapRep
  (Ob a, Ob b) => r
r \\ :: forall (a :: k) (b :: (OPPOSITE k, k)) r.
((Ob a, Ob b) => r) -> ExponentialFunctor a b -> r
\\ ExponentialFunctor a ~> (c ~~> d)
f = r
(Ob a, Ob (c ~~> d)) => r
(Ob a, Ob b) => r
r ((Ob a, Ob (c ~~> d)) => r) -> (a ~> (c ~~> d)) -> r
forall (a :: k) (b :: k) r. ((Ob a, Ob b) => r) -> (a ~> b) -> r
forall {j} {k} (p :: PRO j k) (a :: j) (b :: k) r.
Profunctor p =>
((Ob a, Ob b) => r) -> p a b -> r
\\ a ~> (c ~~> d)
f

instance (Closed k) => Representable (ExponentialFunctor :: PRO k (OPPOSITE k, k)) where
  type ExponentialFunctor % '(OP a, b) = a ~~> b
  index :: forall (a :: k) (b :: (OPPOSITE k, k)).
ExponentialFunctor a b -> a ~> (ExponentialFunctor % b)
index (ExponentialFunctor a ~> (c ~~> d)
f) = a ~> (ExponentialFunctor % b)
a ~> (c ~~> d)
f
  tabulate :: forall (b :: (OPPOSITE k, k)) (a :: k).
Ob b =>
(a ~> (ExponentialFunctor % b)) -> ExponentialFunctor a b
tabulate = (a ~> (ExponentialFunctor % b)) -> ExponentialFunctor a b
(a ~> (UN 'OP (Fst b) ~~> Snd b))
-> ExponentialFunctor a '( 'OP (UN 'OP (Fst b)), Snd b)
forall {k} (c :: k) (d :: k) (a :: k).
(Ob c, Ob d) =>
(a ~> (c ~~> d)) -> ExponentialFunctor a '( 'OP c, d)
ExponentialFunctor
  repMap :: forall (a :: (OPPOSITE k, k)) (b :: (OPPOSITE k, k)).
(a ~> b) -> (ExponentialFunctor % a) ~> (ExponentialFunctor % b)
repMap (Op b1 ~> a1
f :**: a2 ~> b2
g) = a2 ~> b2
g (a2 ~> b2) -> (b1 ~> a1) -> (a1 ~~> a2) ~> (b1 ~~> b2)
forall (b :: k) (y :: k) (x :: k) (a :: k).
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
forall k (b :: k) (y :: k) (x :: k) (a :: k).
Closed k =>
(b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y)
^^^ b1 ~> a1
f

class (Cartesian k, Closed k) => CCC k
instance (Cartesian k, Closed k) => CCC k

class (CCC k, HasCoproducts k) => BiCCC k
instance (CCC k, HasCoproducts k) => BiCCC k

ap
  :: forall {j} {k} y a x p
   . (Cartesian j, Closed k, MonoidalProfunctor (p :: PRO j k), Ob y)
  => p a (x ~~> y)
  -> p a x
  -> p a y
ap :: forall {j} {k} (y :: k) (a :: j) (x :: k) (p :: PRO j k).
(Cartesian j, Closed k, MonoidalProfunctor p, Ob y) =>
p a (x ~~> y) -> p a x -> p a y
ap p a (x ~~> y)
pf p a x
px = (a ~> (a && a))
-> (((x ~~> y) ** x) ~> y) -> p (a && a) ((x ~~> y) ** x) -> p a y
forall (c :: j) (a :: j) (b :: k) (d :: k).
(c ~> a) -> (b ~> d) -> p a b -> p c d
forall {j} {k} (p :: PRO j k) (c :: j) (a :: j) (b :: k) (d :: k).
Profunctor p =>
(c ~> a) -> (b ~> d) -> p a b -> p c d
dimap a ~> (a && a)
forall {k} (a :: k). (HasBinaryProducts k, Ob a) => a ~> (a && a)
diag ((x ~> x) -> (y ~> y) -> ((x ~~> y) ** x) ~> y
forall k (a :: k) (a' :: k) (b :: k) (b' :: k).
Closed k =>
(a ~> a') -> (b ~> b') -> ((a' ~~> b) ** a) ~> b'
eval' (p a x -> x ~> x
forall {k1} {k2} (a :: k2) (b :: k1) (p :: PRO k2 k1).
Profunctor p =>
p a b -> Obj b
tgt p a x
px) (forall (a :: k). (CategoryOf k, Ob a) => Obj a
forall {k} (a :: k). (CategoryOf k, Ob a) => Obj a
obj @y)) (p a (x ~~> y)
pf p a (x ~~> y) -> p a x -> p (a ** a) ((x ~~> y) ** x)
forall (x1 :: j) (x2 :: k) (y1 :: j) (y2 :: k).
p x1 x2 -> p y1 y2 -> p (x1 ** y1) (x2 ** y2)
forall {j} {k} (p :: j +-> k) (x1 :: k) (x2 :: j) (y1 :: k)
       (y2 :: j).
MonoidalProfunctor p =>
p x1 x2 -> p y1 y2 -> p (x1 ** y1) (x2 ** y2)
`par` p a x
px) ((Ob a, Ob (x ~~> y)) => p a y) -> p a (x ~~> y) -> p a y
forall (a :: j) (b :: k) r. ((Ob a, Ob b) => r) -> p a b -> r
forall {j} {k} (p :: PRO j k) (a :: j) (b :: k) r.
Profunctor p =>
((Ob a, Ob b) => r) -> p a b -> r
\\ p a (x ~~> y)
pf