{-# LANGUAGE CPP, MagicHash #-}
{-# OPTIONS_HADDOCK not-home #-}
module Control.Effect.Type.Internal.BaseControl where
import Data.Coerce
import GHC.Exts (Proxy#, proxy#)
import Control.Effect.Internal.Union
import Control.Effect.Internal.Utils
import Control.Effect.Internal.Itself
import Control.Effect.Type.Optional
import Control.Monad
import Control.Monad.Base
import Control.Monad.Trans
import Control.Monad.Trans.Control
import Control.Monad.Trans.Except
import Control.Monad.Trans.Reader
import Control.Monad.Trans.State.Strict as SSt
import Control.Monad.Trans.State.Lazy as LSt
import Control.Monad.Trans.Writer.Lazy as LWr
import Control.Monad.Trans.Writer.Strict as SWr
import Control.Monad.Trans.Writer.CPS as CPSWr
newtype BaseControl b m a where
GainBaseControl :: ( forall z
. (MonadBaseControl b z, Coercible z m)
=> Proxy# z
-> a
)
-> BaseControl b m a
threadBaseControlViaClass :: forall b t m a
. ( MonadTrans t
, Monad m
, forall z
. MonadBaseControl b z
=> MonadBaseControl b (t z)
, forall z
. Coercible z m
=> Coercible (t z) (t m)
)
=> (forall x. BaseControl b m x -> m x)
-> BaseControl b (t m) a -> t m a
threadBaseControlViaClass alg (GainBaseControl main) =
lift $ alg $ GainBaseControl $ \(_ :: Proxy# z) ->
main (proxy# :: Proxy# (t z))
{-# INLINE threadBaseControlViaClass #-}
threadOptionalViaBaseControl :: forall s t m a
. ( Functor s
, Monad m
, Monad (t m)
, ThreadsEff t (BaseControl m)
)
=> (forall x. Optional s m x -> m x)
-> Optional s (t m) a -> t m a
threadOptionalViaBaseControl alg (Optionally sa m) =
join
$ threadEff (\(GainBaseControl main) -> return $ main (proxy# :: Proxy# (Itself m)))
$ GainBaseControl @m $ \(_ :: Proxy# z) ->
coerce $ join $ liftBaseWith @m @z @(z a) $ \lower -> do
coerceAlg alg
$ Optionally (fmap (pure @z) sa)
(fmap restoreM (coerce (lower @a) m))
{-# INLINE threadOptionalViaBaseControl #-}
#define THREAD_BASE_CONTROL(monadT) \
instance ThreadsEff (monadT) (BaseControl b) where \
threadEff = threadBaseControlViaClass; \
{-# INLINE threadEff #-}
#define THREAD_BASE_CONTROL_CTX(ctx, monadT) \
instance ctx => ThreadsEff (monadT) (BaseControl b) where \
threadEff = threadBaseControlViaClass; \
{-# INLINE threadEff #-}
THREAD_BASE_CONTROL(ReaderT i)
THREAD_BASE_CONTROL(ExceptT e)
THREAD_BASE_CONTROL(LSt.StateT s)
THREAD_BASE_CONTROL(SSt.StateT s)
THREAD_BASE_CONTROL_CTX(Monoid w, LWr.WriterT w)
THREAD_BASE_CONTROL_CTX(Monoid w, SWr.WriterT w)
instance Monoid w => ThreadsEff (CPSWr.WriterT w) (BaseControl b) where
threadEff alg (GainBaseControl main) =
lift $ alg $ GainBaseControl $ \(_ :: Proxy# z) ->
main (proxy# :: Proxy# (WriterCPS w z))
{-# INLINE threadEff #-}
newtype WriterCPS s m a = WriterCPS { unWriterCPS :: CPSWr.WriterT s m a }
deriving (Functor, Applicative, Monad)
deriving MonadTrans
instance MonadBase b m => MonadBase b (WriterCPS s m) where
liftBase = lift . liftBase
{-# INLINE liftBase #-}
instance (Monoid s, MonadBaseControl b m)
=> MonadBaseControl b (WriterCPS s m) where
type StM (WriterCPS s m) a = StM m (a, s)
liftBaseWith main = lift $ liftBaseWith $ \run_it ->
main (run_it . CPSWr.runWriterT .# unWriterCPS)
{-# INLINE liftBaseWith #-}
restoreM = WriterCPS #. CPSWr.writerT . restoreM
{-# INLINE restoreM #-}