{-# LANGUAGE UndecidableInstances #-}

module Pandora.Paradigm.Primary.Transformer.Instruction where

import Pandora.Core.Functor (type (:.), type (:=))
import Pandora.Pattern.Category (($))
import Pandora.Pattern.Functor.Covariant (Covariant ((-<$>-)), (-<$$>-))
import Pandora.Pattern.Functor.Pointable (Pointable (point))
import Pandora.Pattern.Functor.Semimonoidal (Semimonoidal (multiply_))
import Pandora.Pattern.Functor.Traversable (Traversable ((<<-)), (-<<-<<-))
import Pandora.Pattern.Functor.Bindable (Bindable ((=<<)))
import Pandora.Pattern.Functor.Monad (Monad)
import Pandora.Pattern.Transformer.Liftable (Liftable (lift))
import Pandora.Pattern.Transformer.Lowerable (Lowerable (lower))
import Pandora.Pattern.Transformer.Hoistable (Hoistable ((/|\), hoist))
import Pandora.Paradigm.Primary.Algebraic.Exponential ()
import Pandora.Paradigm.Primary.Algebraic.Product ((:*:)((:*:)))

data Instruction t a = Enter a | Instruct (t :. Instruction t := a)

instance Covariant t (->) (->) => Covariant (Instruction t) (->) (->) where
	a -> b
f -<$>- :: (a -> b) -> Instruction t a -> Instruction t b
-<$>- Enter a
x = b -> Instruction t b
forall (t :: * -> *) a. a -> Instruction t a
Enter (b -> Instruction t b) -> b -> Instruction t b
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ a -> b
f a
x
	a -> b
f -<$>- Instruct (t :. Instruction t) := a
xs = ((t :. Instruction t) := b) -> Instruction t b
forall (t :: * -> *) a.
((t :. Instruction t) := a) -> Instruction t a
Instruct (((t :. Instruction t) := b) -> Instruction t b)
-> ((t :. Instruction t) := b) -> Instruction t b
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ a -> b
f (a -> b)
-> ((t :. Instruction t) := a) -> (t :. Instruction t) := b
forall (t :: * -> *) (u :: * -> *) (category :: * -> * -> *) a b.
(Covariant u category category, Covariant t category category) =>
category a b -> category (t (u a)) (t (u b))
-<$$>- (t :. Instruction t) := a
xs

instance Covariant t (->) (->) => Pointable (Instruction t) (->) where
	point :: a -> Instruction t a
point = a -> Instruction t a
forall (t :: * -> *) a. a -> Instruction t a
Enter

instance (Covariant t (->) (->), Semimonoidal t (->) (:*:) (:*:)) => Semimonoidal (Instruction t) (->) (:*:) (:*:) where
	multiply_ :: (Instruction t a :*: Instruction t b) -> Instruction t (a :*: b)
multiply_ (Enter a
x :*: Enter b
y) = (a :*: b) -> Instruction t (a :*: b)
forall (t :: * -> *) a. a -> Instruction t a
Enter ((a :*: b) -> Instruction t (a :*: b))
-> (a :*: b) -> Instruction t (a :*: b)
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ a
x a -> b -> a :*: b
forall s a. s -> a -> s :*: a
:*: b
y
	multiply_ (Enter a
x :*: Instruct (t :. Instruction t) := b
y) = (a
x a -> b -> a :*: b
forall s a. s -> a -> s :*: a
:*:) (b -> a :*: b) -> Instruction t b -> Instruction t (a :*: b)
forall (t :: * -> *) (source :: * -> * -> *)
       (target :: * -> * -> *) a b.
Covariant t source target =>
source a b -> target (t a) (t b)
-<$>- ((t :. Instruction t) := b) -> Instruction t b
forall (t :: * -> *) a.
((t :. Instruction t) := a) -> Instruction t a
Instruct (t :. Instruction t) := b
y
	multiply_ (Instruct (t :. Instruction t) := a
x :*: Enter b
y) = (a -> b -> a :*: b
forall s a. s -> a -> s :*: a
:*: b
y) (a -> a :*: b) -> Instruction t a -> Instruction t (a :*: b)
forall (t :: * -> *) (source :: * -> * -> *)
       (target :: * -> * -> *) a b.
Covariant t source target =>
source a b -> target (t a) (t b)
-<$>- ((t :. Instruction t) := a) -> Instruction t a
forall (t :: * -> *) a.
((t :. Instruction t) := a) -> Instruction t a
Instruct (t :. Instruction t) := a
x
	multiply_ (Instruct (t :. Instruction t) := a
x :*: Instruct (t :. Instruction t) := b
y) = ((t :. Instruction t) := (a :*: b)) -> Instruction t (a :*: b)
forall (t :: * -> *) a.
((t :. Instruction t) := a) -> Instruction t a
Instruct (((t :. Instruction t) := (a :*: b)) -> Instruction t (a :*: b))
-> ((t :. Instruction t) := (a :*: b)) -> Instruction t (a :*: b)
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ forall k (t :: k -> *) (p :: * -> * -> *) (source :: * -> * -> *)
       (target :: k -> k -> k) (a :: k) (b :: k).
Semimonoidal t p source target =>
p (source (t a) (t b)) (t (target a b))
forall (target :: * -> * -> *) a b.
Semimonoidal (Instruction t) (->) (:*:) target =>
(Instruction t a :*: Instruction t b) -> Instruction t (target a b)
multiply_ @_ @(->) @(:*:) ((Instruction t a :*: Instruction t b) -> Instruction t (a :*: b))
-> t (Instruction t a :*: Instruction t b)
-> (t :. Instruction t) := (a :*: b)
forall (t :: * -> *) (source :: * -> * -> *)
       (target :: * -> * -> *) a b.
Covariant t source target =>
source a b -> target (t a) (t b)
-<$>- (((t :. Instruction t) := a) :*: ((t :. Instruction t) := b))
-> t (Instruction t a :*: Instruction t b)
forall k (t :: k -> *) (p :: * -> * -> *) (source :: * -> * -> *)
       (target :: k -> k -> k) (a :: k) (b :: k).
Semimonoidal t p source target =>
p (source (t a) (t b)) (t (target a b))
multiply_ ((t :. Instruction t) := a
x ((t :. Instruction t) := a)
-> ((t :. Instruction t) := b)
-> ((t :. Instruction t) := a) :*: ((t :. Instruction t) := b)
forall s a. s -> a -> s :*: a
:*: (t :. Instruction t) := b
y)

instance Covariant t (->) (->) => Bindable (Instruction t) (->) where
	a -> Instruction t b
f =<< :: (a -> Instruction t b) -> Instruction t a -> Instruction t b
=<< Enter a
x = a -> Instruction t b
f a
x
	a -> Instruction t b
f =<< Instruct (t :. Instruction t) := a
xs = ((t :. Instruction t) := b) -> Instruction t b
forall (t :: * -> *) a.
((t :. Instruction t) := a) -> Instruction t a
Instruct (((t :. Instruction t) := b) -> Instruction t b)
-> ((t :. Instruction t) := b) -> Instruction t b
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ (a -> Instruction t b
f (a -> Instruction t b) -> Instruction t a -> Instruction t b
forall (t :: * -> *) (source :: * -> * -> *) a b.
Bindable t source =>
source a (t b) -> source (t a) (t b)
=<<) (Instruction t a -> Instruction t b)
-> ((t :. Instruction t) := a) -> (t :. Instruction t) := b
forall (t :: * -> *) (source :: * -> * -> *)
       (target :: * -> * -> *) a b.
Covariant t source target =>
source a b -> target (t a) (t b)
-<$>- (t :. Instruction t) := a
xs

instance Monad t => Monad (Instruction t) where

instance Traversable t (->) (->) => Traversable (Instruction t) (->) (->) where
	a -> u b
f <<- :: (a -> u b) -> Instruction t a -> u (Instruction t b)
<<- Enter a
x = b -> Instruction t b
forall (t :: * -> *) a. a -> Instruction t a
Enter (b -> Instruction t b) -> u b -> u (Instruction t b)
forall (t :: * -> *) (source :: * -> * -> *)
       (target :: * -> * -> *) a b.
Covariant t source target =>
source a b -> target (t a) (t b)
-<$>- a -> u b
f a
x
	a -> u b
f <<- Instruct (t :. Instruction t) := a
xs = ((t :. Instruction t) := b) -> Instruction t b
forall (t :: * -> *) a.
((t :. Instruction t) := a) -> Instruction t a
Instruct (((t :. Instruction t) := b) -> Instruction t b)
-> u ((t :. Instruction t) := b) -> u (Instruction t b)
forall (t :: * -> *) (source :: * -> * -> *)
       (target :: * -> * -> *) a b.
Covariant t source target =>
source a b -> target (t a) (t b)
-<$>- a -> u b
f (a -> u b)
-> ((t :. Instruction t) := a) -> u ((t :. Instruction t) := b)
forall (t :: * -> *) (u :: * -> *) (v :: * -> *)
       (category :: * -> * -> *) a b.
(Traversable t category category, Covariant u category category,
 Pointable u category, Semimonoidal u category (:*:) (:*:),
 Traversable v category category) =>
category a (u b) -> category (v (t a)) (u (v (t b)))
-<<-<<- (t :. Instruction t) := a
xs

instance Liftable Instruction where
	lift :: u ~> Instruction u
lift u a
x = ((u :. Instruction u) := a) -> Instruction u a
forall (t :: * -> *) a.
((t :. Instruction t) := a) -> Instruction t a
Instruct (((u :. Instruction u) := a) -> Instruction u a)
-> ((u :. Instruction u) := a) -> Instruction u a
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ a -> Instruction u a
forall (t :: * -> *) a. a -> Instruction t a
Enter (a -> Instruction u a) -> u a -> (u :. Instruction u) := a
forall (t :: * -> *) (source :: * -> * -> *)
       (target :: * -> * -> *) a b.
Covariant t source target =>
source a b -> target (t a) (t b)
-<$>- u a
x

instance (forall t . Bindable t (->), forall t . Pointable t (->)) => Lowerable Instruction where
	lower :: Instruction u ~> u
lower (Enter a
x) = a -> u a
forall (t :: * -> *) (source :: * -> * -> *) a.
Pointable t source =>
source a (t a)
point a
x
	lower (Instruct (u :. Instruction u) := a
xs) = Instruction u a -> u a
forall (t :: (* -> *) -> * -> *) (u :: * -> *).
(Lowerable t, Covariant u (->) (->)) =>
t u ~> u
lower (Instruction u a -> u a) -> ((u :. Instruction u) := a) -> u a
forall (t :: * -> *) (source :: * -> * -> *) a b.
Bindable t source =>
source a (t b) -> source (t a) (t b)
=<< (u :. Instruction u) := a
xs

instance (forall v . Covariant v (->) (->)) => Hoistable Instruction where
	u ~> v
_ /|\ :: (u ~> v) -> Instruction u ~> Instruction v
/|\ Enter a
x = a -> Instruction v a
forall (t :: * -> *) a. a -> Instruction t a
Enter a
x
	u ~> v
f /|\ Instruct (u :. Instruction u) := a
xs = ((v :. Instruction v) := a) -> Instruction v a
forall (t :: * -> *) a.
((t :. Instruction t) := a) -> Instruction t a
Instruct (((v :. Instruction v) := a) -> Instruction v a)
-> ((v :. Instruction v) := a) -> Instruction v a
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ (u ~> v) -> Instruction u ~> Instruction v
forall k (t :: (* -> *) -> k -> *) (u :: * -> *) (v :: * -> *).
(Hoistable t, Covariant u (->) (->)) =>
(u ~> v) -> t u ~> t v
hoist u ~> v
f (Instruction u a -> Instruction v a)
-> v (Instruction u a) -> (v :. Instruction v) := a
forall (t :: * -> *) (source :: * -> * -> *)
       (target :: * -> * -> *) a b.
Covariant t source target =>
source a b -> target (t a) (t b)
-<$>- ((u :. Instruction u) := a) -> v (Instruction u a)
u ~> v
f (u :. Instruction u) := a
xs