{-# LANGUAGE UndecidableInstances #-}

module Mensam.Server.Application.Environment where

import Mensam.Server.Application.Environment.Class
import Mensam.Server.Environment

import Control.Monad.Trans
import Control.Monad.Trans.Compose
import Control.Monad.Trans.Control
import Control.Monad.Trans.Control.Identity
import Control.Monad.Trans.Reader
import Data.Kind
import Data.Singletons

type EnvironmentT :: (Type -> Type) -> Type -> Type
newtype EnvironmentT m a = EnvironmentT {forall (m :: * -> *) a. EnvironmentT m a -> ReaderT Environment m a
unEnvironmentT :: ReaderT Environment m a}
  deriving newtype (Functor (EnvironmentT m)
Functor (EnvironmentT m) =>
(forall a. a -> EnvironmentT m a)
-> (forall a b.
    EnvironmentT m (a -> b) -> EnvironmentT m a -> EnvironmentT m b)
-> (forall a b c.
    (a -> b -> c)
    -> EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m c)
-> (forall a b.
    EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m b)
-> (forall a b.
    EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m a)
-> Applicative (EnvironmentT m)
forall a. a -> EnvironmentT m a
forall a b.
EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m a
forall a b.
EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m b
forall a b.
EnvironmentT m (a -> b) -> EnvironmentT m a -> EnvironmentT m b
forall a b c.
(a -> b -> c)
-> EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
forall (m :: * -> *). Applicative m => Functor (EnvironmentT m)
forall (m :: * -> *) a. Applicative m => a -> EnvironmentT m a
forall (m :: * -> *) a b.
Applicative m =>
EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m a
forall (m :: * -> *) a b.
Applicative m =>
EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m b
forall (m :: * -> *) a b.
Applicative m =>
EnvironmentT m (a -> b) -> EnvironmentT m a -> EnvironmentT m b
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c)
-> EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m c
$cpure :: forall (m :: * -> *) a. Applicative m => a -> EnvironmentT m a
pure :: forall a. a -> EnvironmentT m a
$c<*> :: forall (m :: * -> *) a b.
Applicative m =>
EnvironmentT m (a -> b) -> EnvironmentT m a -> EnvironmentT m b
<*> :: forall a b.
EnvironmentT m (a -> b) -> EnvironmentT m a -> EnvironmentT m b
$cliftA2 :: forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c)
-> EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m c
liftA2 :: forall a b c.
(a -> b -> c)
-> EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m c
$c*> :: forall (m :: * -> *) a b.
Applicative m =>
EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m b
*> :: forall a b.
EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m b
$c<* :: forall (m :: * -> *) a b.
Applicative m =>
EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m a
<* :: forall a b.
EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m a
Applicative, (forall a b. (a -> b) -> EnvironmentT m a -> EnvironmentT m b)
-> (forall a b. a -> EnvironmentT m b -> EnvironmentT m a)
-> Functor (EnvironmentT m)
forall a b. a -> EnvironmentT m b -> EnvironmentT m a
forall a b. (a -> b) -> EnvironmentT m a -> EnvironmentT m b
forall (m :: * -> *) a b.
Functor m =>
a -> EnvironmentT m b -> EnvironmentT m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> EnvironmentT m a -> EnvironmentT m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> EnvironmentT m a -> EnvironmentT m b
fmap :: forall a b. (a -> b) -> EnvironmentT m a -> EnvironmentT m b
$c<$ :: forall (m :: * -> *) a b.
Functor m =>
a -> EnvironmentT m b -> EnvironmentT m a
<$ :: forall a b. a -> EnvironmentT m b -> EnvironmentT m a
Functor, Applicative (EnvironmentT m)
Applicative (EnvironmentT m) =>
(forall a b.
 EnvironmentT m a -> (a -> EnvironmentT m b) -> EnvironmentT m b)
-> (forall a b.
    EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m b)
-> (forall a. a -> EnvironmentT m a)
-> Monad (EnvironmentT m)
forall a. a -> EnvironmentT m a
forall a b.
EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m b
forall a b.
EnvironmentT m a -> (a -> EnvironmentT m b) -> EnvironmentT m b
forall (m :: * -> *). Monad m => Applicative (EnvironmentT m)
forall (m :: * -> *) a. Monad m => a -> EnvironmentT m a
forall (m :: * -> *) a b.
Monad m =>
EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m b
forall (m :: * -> *) a b.
Monad m =>
EnvironmentT m a -> (a -> EnvironmentT m b) -> EnvironmentT m b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
EnvironmentT m a -> (a -> EnvironmentT m b) -> EnvironmentT m b
>>= :: forall a b.
EnvironmentT m a -> (a -> EnvironmentT m b) -> EnvironmentT m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m b
>> :: forall a b.
EnvironmentT m a -> EnvironmentT m b -> EnvironmentT m b
$creturn :: forall (m :: * -> *) a. Monad m => a -> EnvironmentT m a
return :: forall a. a -> EnvironmentT m a
Monad)
  deriving newtype ((forall (m :: * -> *). Monad m => Monad (EnvironmentT m)) =>
(forall (m :: * -> *) a. Monad m => m a -> EnvironmentT m a)
-> MonadTrans EnvironmentT
forall (m :: * -> *). Monad m => Monad (EnvironmentT m)
forall (m :: * -> *) a. Monad m => m a -> EnvironmentT m a
forall (t :: (* -> *) -> * -> *).
(forall (m :: * -> *). Monad m => Monad (t m)) =>
(forall (m :: * -> *) a. Monad m => m a -> t m a) -> MonadTrans t
$clift :: forall (m :: * -> *) a. Monad m => m a -> EnvironmentT m a
lift :: forall (m :: * -> *) a. Monad m => m a -> EnvironmentT m a
MonadTrans, MonadTrans EnvironmentT
MonadTrans EnvironmentT =>
(forall (m :: * -> *) a.
 Monad m =>
 (Run EnvironmentT -> m a) -> EnvironmentT m a)
-> (forall (m :: * -> *) a.
    Monad m =>
    m (StT EnvironmentT a) -> EnvironmentT m a)
-> MonadTransControl EnvironmentT
forall (m :: * -> *) a.
Monad m =>
m (StT EnvironmentT a) -> EnvironmentT m a
forall (m :: * -> *) a.
Monad m =>
(Run EnvironmentT -> m a) -> EnvironmentT m a
forall (t :: (* -> *) -> * -> *).
MonadTrans t =>
(forall (m :: * -> *) a. Monad m => (Run t -> m a) -> t m a)
-> (forall (m :: * -> *) a. Monad m => m (StT t a) -> t m a)
-> MonadTransControl t
$cliftWith :: forall (m :: * -> *) a.
Monad m =>
(Run EnvironmentT -> m a) -> EnvironmentT m a
liftWith :: forall (m :: * -> *) a.
Monad m =>
(Run EnvironmentT -> m a) -> EnvironmentT m a
$crestoreT :: forall (m :: * -> *) a.
Monad m =>
m (StT EnvironmentT a) -> EnvironmentT m a
restoreT :: forall (m :: * -> *) a.
Monad m =>
m (StT EnvironmentT a) -> EnvironmentT m a
MonadTransControl, MonadTransControl EnvironmentT
MonadTransControl EnvironmentT =>
(forall (m :: * -> *) a.
 Monad m =>
 ((forall x. EnvironmentT m x -> m x) -> m a) -> EnvironmentT m a)
-> MonadTransControlIdentity EnvironmentT
forall (m :: * -> *) a.
Monad m =>
((forall x. EnvironmentT m x -> m x) -> m a) -> EnvironmentT m a
forall (t :: (* -> *) -> * -> *).
MonadTransControl t =>
(forall (m :: * -> *) a.
 Monad m =>
 ((forall x. t m x -> m x) -> m a) -> t m a)
-> MonadTransControlIdentity t
$cliftWithIdentity :: forall (m :: * -> *) a.
Monad m =>
((forall x. EnvironmentT m x -> m x) -> m a) -> EnvironmentT m a
liftWithIdentity :: forall (m :: * -> *) a.
Monad m =>
((forall x. EnvironmentT m x -> m x) -> m a) -> EnvironmentT m a
MonadTransControlIdentity)

instance Monad m => MonadEnvironment (EnvironmentT m) where
  environmentVariable ::
    forall envVar.
    SingI envVar =>
    ProxyEnvVarName (EnvVarName envVar) ->
    EnvironmentT m (EnvVarValue envVar)
  environmentVariable :: forall (envVar :: EnvVar).
SingI envVar =>
ProxyEnvVarName (EnvVarName envVar)
-> EnvironmentT m (EnvVarValue envVar)
environmentVariable ProxyEnvVarName (EnvVarName envVar)
_ = do
    Environment
environment <- ReaderT Environment m Environment -> EnvironmentT m Environment
forall (m :: * -> *) a. ReaderT Environment m a -> EnvironmentT m a
EnvironmentT ReaderT Environment m Environment
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask
    let accessEnvVar :: SEnvVar envVar -> EnvVarValue envVar
accessEnvVar = Environment
-> forall (envVar :: EnvVar). SEnvVar envVar -> EnvVarValue envVar
getEnvironment Environment
environment
    EnvVarValue envVar -> EnvironmentT m (EnvVarValue envVar)
forall a. a -> EnvironmentT m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (EnvVarValue envVar -> EnvironmentT m (EnvVarValue envVar))
-> EnvVarValue envVar -> EnvironmentT m (EnvVarValue envVar)
forall a b. (a -> b) -> a -> b
$ SEnvVar envVar -> EnvVarValue envVar
accessEnvVar (SEnvVar envVar -> EnvVarValue envVar)
-> SEnvVar envVar -> EnvVarValue envVar
forall a b. (a -> b) -> a -> b
$ forall {k} (a :: k). SingI a => Sing a
forall (a :: EnvVar). SingI a => Sing a
sing @envVar

deriving via
  EnvironmentT ((t2 :: (Type -> Type) -> Type -> Type) m)
  instance
    Monad (t2 m) => MonadEnvironment (ComposeT EnvironmentT t2 m)

runEnvironmentT :: Environment -> EnvironmentT m a -> m a
runEnvironmentT :: forall (m :: * -> *) a. Environment -> EnvironmentT m a -> m a
runEnvironmentT Environment
env EnvironmentT m a
tma = ReaderT Environment m a -> Environment -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (EnvironmentT m a -> ReaderT Environment m a
forall (m :: * -> *) a. EnvironmentT m a -> ReaderT Environment m a
unEnvironmentT EnvironmentT m a
tma) Environment
env