{-# LANGUAGE UndecidableInstances #-}

module Pandora.Paradigm.Primary.Transformer.Yoneda where

import Pandora.Pattern.Semigroupoid ((.))
import Pandora.Pattern.Category ((<--))
import Pandora.Pattern.Functor.Covariant (Covariant ((<-|-)))
import Pandora.Pattern.Transformer.Liftable (Liftable (lift))
import Pandora.Paradigm.Algebraic.Exponential ()

newtype Yoneda t a = Yoneda
	{ Yoneda t a -> forall b. (a -> b) -> t b
yoneda :: forall b . (a -> b) -> t b }

instance Covariant (->) (->) (Yoneda t) where
	a -> b
f <-|- :: (a -> b) -> Yoneda t a -> Yoneda t b
<-|- Yoneda t a
x = (forall b. (b -> b) -> t b) -> Yoneda t b
forall (t :: * -> *) a. (forall b. (a -> b) -> t b) -> Yoneda t a
Yoneda (\b -> b
k -> Yoneda t a -> forall b. (a -> b) -> t b
forall (t :: * -> *) a. Yoneda t a -> forall b. (a -> b) -> t b
yoneda Yoneda t a
x ((a -> b) -> t b) -> (a -> b) -> t b
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
<-- b -> b
k (b -> b) -> (a -> b) -> a -> b
forall (m :: * -> * -> *) b c a.
Semigroupoid m =>
m b c -> m a b -> m a c
. a -> b
f)

instance Liftable (->) Yoneda where
	lift :: u a -> Yoneda u a
lift u a
x = (forall b. (a -> b) -> u b) -> Yoneda u a
forall (t :: * -> *) a. (forall b. (a -> b) -> t b) -> Yoneda t a
Yoneda ((a -> b) -> u a -> u b
forall (source :: * -> * -> *) (target :: * -> * -> *)
       (t :: * -> *) a b.
Covariant source target t =>
source a b -> target (t a) (t b)
<-|- u a
x)