{-# OPTIONS_GHC -fno-warn-orphans #-}

module Pandora.Paradigm.Inventory.Environment (Environment (..), Configured, env) where

import Pandora.Core.Appliable ((!))
import Pandora.Pattern.Semigroupoid ((.))
import Pandora.Pattern.Category (identity, ($))
import Pandora.Pattern.Functor.Covariant (Covariant ((<$>)))
import Pandora.Pattern.Functor.Contravariant (Contravariant ((>$<)))
import Pandora.Pattern.Functor.Semimonoidal (Semimonoidal (mult))
import Pandora.Pattern.Functor.Monoidal (Monoidal (unit))
import Pandora.Pattern.Functor.Distributive (Distributive ((-<<)))
import Pandora.Pattern.Functor.Bindable (Bindable ((=<<)))
import Pandora.Pattern.Functor.Monad (Monad)
import Pandora.Pattern.Functor.Divariant (Divariant ((>->)))
import Pandora.Pattern.Functor.Bivariant ((<->))
import Pandora.Paradigm.Primary.Algebraic.Exponential (type (-->), (%))
import Pandora.Paradigm.Primary.Algebraic ()
import Pandora.Paradigm.Primary.Algebraic.Product ((:*:))
import Pandora.Paradigm.Primary.Algebraic.One (One (One))
import Pandora.Paradigm.Primary.Algebraic (point)
import Pandora.Pattern.Morphism.Flip (Flip (Flip))
import Pandora.Pattern.Morphism.Straight (Straight (Straight))
import Pandora.Paradigm.Controlflow.Effect.Interpreted (Schematic, Interpreted (Primary, run, unite))
import Pandora.Paradigm.Controlflow.Effect.Transformer.Monadic (Monadic (wrap), (:>) (TM))
import Pandora.Paradigm.Controlflow.Effect.Adaptable (Adaptable (adapt))
import Pandora.Paradigm.Schemes.TU (TU (TU), type (<:.>))

newtype Environment e a = Environment (e -> a)

instance Covariant (->) (->) (Environment e) where
	a -> b
f <$> :: (a -> b) -> Environment e a -> Environment e b
<$> Environment e -> a
x = (e -> b) -> Environment e b
forall e a. (e -> a) -> Environment e a
Environment ((e -> b) -> Environment e b) -> (e -> b) -> Environment e b
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ a -> b
f (a -> b) -> (e -> a) -> e -> b
forall (m :: * -> * -> *) b c a.
Semigroupoid m =>
m b c -> m a b -> m a c
. e -> a
x

instance Contravariant (->) (->) (Flip Environment a) where
	a -> b
f >$< :: (a -> b) -> Flip Environment a b -> Flip Environment a a
>$< Flip (Environment b -> a
g) = Environment a a -> Flip Environment a a
forall (v :: * -> * -> *) a e. v e a -> Flip v a e
Flip (Environment a a -> Flip Environment a a)
-> ((a -> a) -> Environment a a)
-> (a -> a)
-> Flip Environment a a
forall (m :: * -> * -> *) b c a.
Semigroupoid m =>
m b c -> m a b -> m a c
. (a -> a) -> Environment a a
forall e a. (e -> a) -> Environment e a
Environment ((a -> a) -> Flip Environment a a)
-> (a -> a) -> Flip Environment a a
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ b -> a
g (b -> a) -> (a -> b) -> a -> a
forall (m :: * -> * -> *) b c a.
Semigroupoid m =>
m b c -> m a b -> m a c
. a -> b
f

instance Semimonoidal (-->) (:*:) (:*:) (Environment e) where
	mult :: (Environment e a :*: Environment e b) --> Environment e (a :*: b)
mult = ((Environment e a :*: Environment e b) -> Environment e (a :*: b))
-> (Environment e a :*: Environment e b)
   --> Environment e (a :*: b)
forall (v :: * -> * -> *) a e. v a e -> Straight v a e
Straight (((Environment e a :*: Environment e b) -> Environment e (a :*: b))
 -> (Environment e a :*: Environment e b)
    --> Environment e (a :*: b))
-> ((Environment e a :*: Environment e b)
    -> Environment e (a :*: b))
-> (Environment e a :*: Environment e b)
   --> Environment e (a :*: b)
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ (e -> a :*: b) -> Environment e (a :*: b)
forall e a. (e -> a) -> Environment e a
Environment ((e -> a :*: b) -> Environment e (a :*: b))
-> ((Environment e a :*: Environment e b) -> e -> a :*: b)
-> (Environment e a :*: Environment e b)
-> Environment e (a :*: b)
forall (m :: * -> * -> *) b c a.
Semigroupoid m =>
m b c -> m a b -> m a c
. (forall k (p :: * -> * -> *) (source :: * -> * -> *)
       (target :: k -> k -> k) (t :: k -> *) (a :: k) (b :: k).
Semimonoidal p source target t =>
p (source (t a) (t b)) (t (target a b))
forall (source :: * -> * -> *) (target :: * -> * -> *)
       (t :: * -> *) a b.
Semimonoidal (-->) source target t =>
source (t a) (t b) --> t (target a b)
mult @(-->) (((e -> a) :*: (e -> b)) --> (e -> a :*: b))
-> ((e -> a) :*: (e -> b)) -> e -> a :*: b
forall k k k k (m :: k -> k -> *) (a :: k) (b :: k)
       (n :: k -> k -> *) (c :: k) (d :: k).
Appliable m a b n c d =>
m a b -> n c d
!) (((e -> a) :*: (e -> b)) -> e -> a :*: b)
-> ((Environment e a :*: Environment e b) -> (e -> a) :*: (e -> b))
-> (Environment e a :*: Environment e b)
-> e
-> a :*: b
forall (m :: * -> * -> *) b c a.
Semigroupoid m =>
m b c -> m a b -> m a c
. (forall (t :: * -> *) a. Interpreted (->) t => t a -> Primary t a
forall (m :: * -> * -> *) (t :: * -> *) a.
Interpreted m t =>
m (t a) (Primary t a)
run @(->) (Environment e a -> e -> a)
-> (Environment e b -> e -> b)
-> (Environment e a :*: Environment e b)
-> (e -> a) :*: (e -> b)
forall (left :: * -> * -> *) (right :: * -> * -> *)
       (target :: * -> * -> *) (v :: * -> * -> *) a b c d.
Bivariant left right target v =>
left a b -> right c d -> target (v a c) (v b d)
<-> forall (t :: * -> *) a. Interpreted (->) t => t a -> Primary t a
forall (m :: * -> * -> *) (t :: * -> *) a.
Interpreted m t =>
m (t a) (Primary t a)
run @(->))

instance Monoidal (-->) (->) (:*:) (:*:) (Environment e) where
	unit :: Proxy (:*:) -> (Unit (:*:) -> a) --> Environment e a
unit Proxy (:*:)
_ = ((One -> a) -> Environment e a)
-> Straight (->) (One -> a) (Environment e a)
forall (v :: * -> * -> *) a e. v a e -> Straight v a e
Straight (((One -> a) -> Environment e a)
 -> Straight (->) (One -> a) (Environment e a))
-> ((One -> a) -> Environment e a)
-> Straight (->) (One -> a) (Environment e a)
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ \One -> a
f -> (e -> a) -> Environment e a
forall e a. (e -> a) -> Environment e a
Environment ((e -> a) -> Environment e a) -> (e -> a) -> Environment e a
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ \e
_ -> One -> a
f One
One

instance Distributive (->) (->) (Environment e) where
	a -> Environment e b
f -<< :: (a -> Environment e b) -> u a -> Environment e (u b)
-<< u a
g = (e -> u b) -> Environment e (u b)
forall e a. (e -> a) -> Environment e a
Environment ((e -> u b) -> Environment e (u b))
-> (e -> u b) -> Environment e (u b)
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ (forall (t :: * -> *) a. Interpreted (->) t => t a -> Primary t a
forall (m :: * -> * -> *) (t :: * -> *) a.
Interpreted m t =>
m (t a) (Primary t a)
run @(->) (Environment e b -> e -> b)
-> (a -> Environment e b) -> a -> e -> b
forall (source :: * -> * -> *) (target :: * -> * -> *)
       (t :: * -> *) a b.
Covariant source target t =>
source a b -> target (t a) (t b)
<$> a -> Environment e b
f) (a -> e -> b) -> u a -> e -> u b
forall (source :: * -> * -> *) (target :: * -> * -> *)
       (t :: * -> *) (u :: * -> *) a b.
(Distributive source target t, Covariant source target u) =>
source a (t b) -> target (u a) (t (u b))
-<< u a
g

instance Bindable (->) (Environment e) where
	a -> Environment e b
f =<< :: (a -> Environment e b) -> Environment e a -> Environment e b
=<< Environment e -> a
x = (e -> b) -> Environment e b
forall e a. (e -> a) -> Environment e a
Environment ((e -> b) -> Environment e b) -> (e -> b) -> Environment e b
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ \e
e -> (Environment e b -> e -> b
forall (m :: * -> * -> *) (t :: * -> *) a.
Interpreted m t =>
m (t a) (Primary t a)
run (Environment e b -> e -> b) -> e -> Environment e b -> b
forall a b c. (a -> b -> c) -> b -> a -> c
% e
e) (Environment e b -> b) -> (e -> Environment e b) -> e -> b
forall (m :: * -> * -> *) b c a.
Semigroupoid m =>
m b c -> m a b -> m a c
. a -> Environment e b
f (a -> Environment e b) -> (e -> a) -> e -> Environment e b
forall (m :: * -> * -> *) b c a.
Semigroupoid m =>
m b c -> m a b -> m a c
. e -> a
x (e -> b) -> e -> b
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ e
e

--instance Monad (Environment e) where

instance Divariant (->) (->) (->) Environment where
	>-> :: (a -> b) -> (c -> d) -> Environment b c -> Environment a d
(>->) a -> b
ab c -> d
cd Environment b c
bc = (a -> d) -> Environment a d
forall e a. (e -> a) -> Environment e a
Environment ((a -> d) -> Environment a d) -> (a -> d) -> Environment a d
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ a -> b
ab (a -> b) -> (c -> d) -> (b -> c) -> a -> d
forall (left :: * -> * -> *) (right :: * -> * -> *)
       (target :: * -> * -> *) (v :: * -> * -> *) a b c d.
Divariant left right target v =>
left a b -> right c d -> target (v b c) (v a d)
>-> c -> d
cd ((b -> c) -> a -> d) -> (b -> c) -> a -> d
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ Environment b c -> b -> c
forall (m :: * -> * -> *) (t :: * -> *) a.
Interpreted m t =>
m (t a) (Primary t a)
run Environment b c
bc

instance Interpreted (->) (Environment e) where
	type Primary (Environment e) a = (->) e a
	run :: Environment e a -> Primary (Environment e) a
run ~(Environment e -> a
x) = Primary (Environment e) a
e -> a
x
	unite :: Primary (Environment e) a -> Environment e a
unite = Primary (Environment e) a -> Environment e a
forall e a. (e -> a) -> Environment e a
Environment

type instance Schematic Monad (Environment e) = (<:.>) ((->) e)

instance Monadic (Environment e) where
	wrap :: Environment e ~> (Environment e :> u)
wrap Environment e a
x = (<:.>) ((->) e) u a -> (:>) (Environment e) u a
forall (t :: * -> *) (u :: * -> *) a.
Schematic Monad t u a -> (:>) t u a
TM ((<:.>) ((->) e) u a -> (:>) (Environment e) u a)
-> ((((->) e :. u) := a) -> (<:.>) ((->) e) u a)
-> (((->) e :. u) := a)
-> (:>) (Environment e) u a
forall (m :: * -> * -> *) b c a.
Semigroupoid m =>
m b c -> m a b -> m a c
. (((->) e :. u) := a) -> (<:.>) ((->) e) u a
forall k k k k (ct :: k) (cu :: k) (t :: k -> *) (u :: k -> k)
       (a :: k).
((t :. u) := a) -> TU ct cu t u a
TU ((((->) e :. u) := a) -> (:>) (Environment e) u a)
-> (((->) e :. u) := a) -> (:>) (Environment e) u a
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ a -> u a
forall (t :: * -> *) a. Pointable t => a -> t a
point (a -> u a) -> (e -> a) -> ((->) e :. u) := a
forall (source :: * -> * -> *) (target :: * -> * -> *)
       (t :: * -> *) a b.
Covariant source target t =>
source a b -> target (t a) (t b)
<$> Environment e a -> e -> a
forall (m :: * -> * -> *) (t :: * -> *) a.
Interpreted m t =>
m (t a) (Primary t a)
run Environment e a
x

type Configured e = Adaptable (Environment e)

env :: Configured e t => t e
env :: t e
env = Environment e e -> t e
forall k (t :: k -> *) (u :: k -> *). Adaptable t u => t ~> u
adapt (Environment e e -> t e) -> Environment e e -> t e
forall (m :: * -> * -> *) a b. Category m => m (m a b) (m a b)
$ (e -> e) -> Environment e e
forall e a. (e -> a) -> Environment e a
Environment e -> e
forall (m :: * -> * -> *) a. Category m => m a a
identity