{-# LANGUAGE AllowAmbiguousTypes, DerivingVia #-}
{-# OPTIONS_HADDOCK not-home #-}
module Control.Effect.Carrier.Internal.Interpret where
import Data.Coerce
import Control.Applicative
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Trans.Reader
import Control.Monad.Fix
import Control.Monad.Trans.Identity
import Control.Effect.Internal
import Control.Effect.Internal.Derive
import Control.Effect.Internal.Itself
import Control.Effect.Internal.KnownList
import Control.Effect.Internal.Union
import Control.Effect.Internal.Effly
import Control.Effect.Internal.Reflection
import Control.Effect.Internal.Utils
import Control.Monad.Base
import Control.Effect.Carrier.Internal.Intro
data HandlerCState p m z
= HandlerCState (forall x. m x -> z x) (Algebra p z)
newtype ReifiedReformulation r p m = ReifiedReformulation {
getReifiedReformulation :: Reformulation r p m
}
newtype
HandlerC
(sHandler :: *)
(sReform :: *)
(r :: [Effect])
(p :: [Effect])
(m :: * -> *) z (a :: *)
= HandlerC { unHandlerC :: z a }
deriving (Functor, Applicative, Monad) via z
data CarrierReform m
instance (Carrier m, r ~ Derivs m, p ~ Prims m)
=> Reifies (CarrierReform m)
(ReifiedReformulation r p m) where
reflect = ReifiedReformulation reformulate
{-# INLINE reflect #-}
instance ( Reifies sHandler (HandlerCState p m z)
, Reifies sReform (ReifiedReformulation r p m)
, Monad z
)
=> Carrier (HandlerC sHandler sReform r p m z) where
type Derivs (HandlerC sHandler sReform r p m z) = r
type Prims (HandlerC sHandler sReform r p m z) = p
algPrims =
let
HandlerCState _ alg = reflect @sHandler
in
coerce #. alg .# coerce
{-# INLINE algPrims #-}
reformulate n' alg =
let
HandlerCState n _ = reflect @sHandler
in
getReifiedReformulation (reflect @sReform) (n' . HandlerC #. n) alg
{-# INLINE reformulate #-}
algDerivs =
let
HandlerCState n alg = reflect @sHandler
in
getReifiedReformulation
(reflect @sReform)
(HandlerC #. n)
(coerce #. alg .# coerce)
{-# INLINE algDerivs #-}
instance ( Reifies sHandler (HandlerCState p m z)
, Monad z
, Monad m
)
=> MonadBase m (HandlerC sHandler sReform r p m z) where
liftBase m =
let
HandlerCState n _ = reflect @sHandler
in
HandlerC (n m)
{-# INLINE liftBase #-}
newtype InterpretPrimC (s :: *) (e :: Effect) (m :: * -> *) a =
InterpretPrimC {
unInterpretPrimC :: m a
}
deriving ( Functor, Applicative, Monad
, Alternative, MonadPlus
, MonadFix, MonadFail, MonadIO
, MonadThrow, MonadCatch, MonadMask
, MonadBase b, MonadBaseControl b
)
deriving (MonadTrans, MonadTransControl) via IdentityT
class ( RepresentationalEff e
, Carrier m
)
=> Handler (h :: *) e m where
effHandler :: EffHandler e m
type EffHandler e m =
forall z x
. ( Carrier z
, Derivs z ~ Derivs m
, Prims z ~ Prims m
, MonadBase m z
)
=> e (Effly z) x -> Effly z x
type EffPrimHandler e m = forall x. e m x -> m x
class ( RepresentationalEff e
, Carrier m
) => PrimHandler (h :: *) e m where
effPrimHandler :: EffPrimHandler e m
instance ( Carrier m
, Handler h e m
) => Carrier (InterpretC h e m) where
type Derivs (InterpretC h e m) = e ': Derivs m
type Prims (InterpretC h e m) = Prims m
algPrims = coerce (algPrims @m)
{-# INLINEABLE algPrims #-}
reformulate n alg = powerAlg (reformulate (n .# InterpretC) alg) $
let
!handlerState = HandlerCState (n .# InterpretC) alg
in
reify handlerState $ \(_ :: p s) ->
\e -> unHandlerC @s @(CarrierReform m) @_ @_ @m $ runEffly $
effHandler @h @e @m (coerce e)
{-# INLINEABLE reformulate #-}
algDerivs = powerAlg (coerce (algDerivs @m)) $ \e ->
InterpretC $ unItself $ runEffly $ effHandler @h @e (coerce e)
{-# INLINEABLE algDerivs #-}
newtype InterpretC (h :: *) (e :: Effect) (m :: * -> *) a = InterpretC {
unInterpretC :: m a
}
deriving ( Functor, Applicative, Monad
, Alternative, MonadPlus
, MonadFix, MonadFail, MonadIO
, MonadThrow, MonadCatch, MonadMask
, MonadBase b, MonadBaseControl b
)
deriving (MonadTrans, MonadTransControl) via IdentityT
newtype ReifiedHandler e m = ReifiedHandler {
getReifiedHandler :: EffHandler e m
}
newtype ReifiedPrimHandler (e :: Effect) m = ReifiedPrimHandler {
getReifiedPrimHandler :: forall z x. Coercible z m => e z x -> m x
}
coerceHandler :: (RepresentationalEff e, Coercible m n)
=> (e m a -> m a) -> e n a -> n a
coerceHandler = coerce
{-# INLINE coerceHandler #-}
instance PrimHandler h e m => Carrier (InterpretPrimC h e m) where
type Derivs (InterpretPrimC h e m) = e ': Derivs m
type Prims (InterpretPrimC h e m) = e ': Prims m
algPrims =
powerAlg
(coerce (algPrims @m))
(coerceHandler (effPrimHandler @h @e @m))
{-# INLINEABLE algPrims #-}
reformulate = addPrim (coerceReform (reformulate @m))
{-# INLINEABLE reformulate #-}
algDerivs =
powerAlg
(coerce (algDerivs @m))
(coerceHandler (effPrimHandler @h @e @m))
{-# INLINEABLE algDerivs #-}
data ViaReifiedH (s :: *)
instance ( RepresentationalEff e
, Carrier m
, Reifies s (ReifiedHandler e m)
) => Handler (ViaReifiedH s) e m where
effHandler = getReifiedHandler (reflect @s)
{-# INLINE effHandler #-}
instance ( RepresentationalEff e
, Carrier m
, Reifies s (ReifiedPrimHandler e m)
) => PrimHandler (ViaReifiedH s) e m where
effPrimHandler = getReifiedPrimHandler (reflect @s)
{-# INLINE effPrimHandler #-}
type InterpretReifiedC e m a =
forall s
. ReifiesHandler s e m
=> InterpretC (ViaReifiedH s) e m a
type InterpretPrimReifiedC e m a =
forall s
. ReifiesPrimHandler s e m
=> InterpretPrimC (ViaReifiedH s) e m a
newtype InterpretSimpleC (e :: Effect) (m :: * -> *) a = InterpretSimpleC {
unInterpretSimpleC :: ReaderT (ReifiedHandler e m) m a
}
deriving ( Functor, Applicative, Monad
, Alternative, MonadPlus
, MonadFix, MonadFail, MonadIO
, MonadThrow, MonadCatch, MonadMask
, MonadBase b, MonadBaseControl b
)
via ReaderT (ReifiedHandler e m) m
instance MonadTrans (InterpretSimpleC e) where
lift m = InterpretSimpleC (lift m)
{-# INLINE lift #-}
instance ( Threads (ReaderT (ReifiedHandler e m)) (Prims m)
, RepresentationalEff e
, Carrier m
)
=> Carrier (InterpretSimpleC e m) where
type Derivs (InterpretSimpleC e m) = e ': Derivs m
type Prims (InterpretSimpleC e m) = Prims m
algPrims = coerceAlg (thread @(ReaderT (ReifiedHandler e m)) (algPrims @m))
{-# INLINEABLE algPrims #-}
reformulate n alg = powerAlg (reformulate (n . lift) alg) $ \e -> do
ReifiedHandler handler <- n (InterpretSimpleC ask)
let !handlerState = HandlerCState (n . lift) alg
reify handlerState $ \(_ :: p s) ->
unHandlerC @s @(CarrierReform m) @_ @_ @m $ runEffly $
handler (coerce e)
{-# INLINEABLE reformulate #-}
newtype InterpretPrimSimpleC (e :: Effect) (m :: * -> *) a =
InterpretPrimSimpleC {
unInterpretPrimSimpleC :: ReaderT (ReifiedPrimHandler e m) m a
}
deriving ( Functor, Applicative, Monad
, Alternative, MonadPlus
, MonadFix, MonadFail, MonadIO
, MonadThrow, MonadCatch, MonadMask
, MonadBase b, MonadBaseControl b
)
via ReaderT (ReifiedPrimHandler e m) m
instance MonadTrans (InterpretPrimSimpleC e) where
lift m = InterpretPrimSimpleC (lift m)
{-# INLINE lift #-}
instance ( Threads (ReaderT (ReifiedPrimHandler e m)) (Prims m)
, ThreadsEff (ReaderT (ReifiedPrimHandler e m)) e
, RepresentationalEff e
, Carrier m
)
=> Carrier (InterpretPrimSimpleC e m) where
type Derivs (InterpretPrimSimpleC e m) = e ': Derivs m
type Prims (InterpretPrimSimpleC e m) = e ': Prims m
algPrims =
powerAlg
(coerce (thread @(ReaderT (ReifiedPrimHandler e m)) (algPrims @m)))
$ \e -> InterpretPrimSimpleC $ ReaderT $ \rh@(ReifiedPrimHandler h) ->
runReaderT (threadEff @(ReaderT (ReifiedPrimHandler e m)) h (coerce e)) rh
{-# INLINEABLE algPrims #-}
reformulate = addPrim (liftReform reformulate)
{-# INLINEABLE reformulate #-}
interpret :: forall e m a
. (RepresentationalEff e, Carrier m)
=> EffHandler e m
-> InterpretReifiedC e m a
-> m a
interpret h m = reify (ReifiedHandler h) $ \(_ :: p s) ->
unInterpretC @(ViaReifiedH s) m
{-# INLINE interpret #-}
interpretSimple
:: forall e m a p
. ( RepresentationalEff e
, Threaders '[ReaderThreads] m p
, Carrier m
)
=> EffHandler e m
-> InterpretSimpleC e m a
-> m a
interpretSimple h m = coerce m (ReifiedHandler @e @m h)
{-# INLINE interpretSimple #-}
interpretViaHandler :: forall h e m a
. Handler h e m
=> InterpretC h e m a
-> m a
interpretViaHandler = unInterpretC
{-# INLINE interpretViaHandler #-}
interpretPrim :: forall e m a
. (RepresentationalEff e, Carrier m)
=> EffPrimHandler e m
-> InterpretPrimReifiedC e m a
-> m a
interpretPrim h m =
let
int :: ReifiedPrimHandler e m
int = ReifiedPrimHandler (h .# coerce)
in
reify int $
\(_ :: p s) -> interpretPrimViaHandler @(ViaReifiedH s) m
{-# INLINE interpretPrim #-}
interpretPrimViaHandler
:: forall h e m a
. PrimHandler h e m
=> InterpretPrimC h e m a
-> m a
interpretPrimViaHandler = unInterpretPrimC
{-# INLINE interpretPrimViaHandler #-}
interpretPrimSimple
:: forall e m a p
. ( RepresentationalEff e
, Threaders '[ReaderThreads] m p
, ReaderThreads '[e]
, Carrier m
)
=> EffPrimHandler e m
-> InterpretPrimSimpleC e m a
-> m a
interpretPrimSimple h m = coerce m (ReifiedPrimHandler @e @m (h .# coerce))
{-# INLINE interpretPrimSimple #-}
addDeriv :: ( RepresentationalEff e
, Monad m
)
=> ( forall z x
. ( Carrier z
, Derivs z ~ r
, Prims z ~ p
, MonadBase m z
)
=> e (Effly z) x -> Effly z x
)
-> Reformulation r p m
-> Reformulation (e ': r) p m
addDeriv !h !reform = \ !n !alg ->
let
!handlerState = HandlerCState n alg
in
reify handlerState $ \(_ :: pr sHandler) ->
reify (ReifiedReformulation reform) $ \(_ :: pr sReform) ->
powerAlg (reform n alg) $ \e ->
unHandlerC @sHandler @sReform $ runEffly $ h (coerce e)
{-# INLINE addDeriv #-}
newtype ReinterpretC h e new m a = ReinterpretC {
unReinterpretC :: IntroUnderC e new (InterpretC h e m) a
}
deriving ( Functor, Applicative, Monad
, Alternative, MonadPlus
, MonadFix, MonadFail, MonadIO
, MonadThrow, MonadCatch, MonadMask
, MonadBase b, MonadBaseControl b
)
deriving (MonadTrans, MonadTransControl) via IdentityT
deriving
via
IntroUnderC e new (InterpretC h e m)
instance
( Handler h e m
, Carrier m
, KnownList new
, IntroConsistent '[] new m
)
=> Carrier (ReinterpretC h e new m)
type ReifiesHandler s e m = Reifies s (ReifiedHandler e m)
type ReifiesPrimHandler s e m = Reifies s (ReifiedPrimHandler e m)
type ReinterpretReifiedC e new m a =
forall s
. ReifiesHandler s e m
=> ReinterpretC (ViaReifiedH s) e new m a
reinterpret :: forall e new m a
. ( RepresentationalEff e
, KnownList new
, HeadEffs new m
)
=> EffHandler e m
-> ReinterpretReifiedC e new m a
-> m a
reinterpret h main = interpret h $ introUnder (unReinterpretC main)
{-# INLINE reinterpret #-}
reinterpretViaHandler :: forall h e new m a
. ( Handler h e m
, KnownList new
, HeadEffs new m
)
=> ReinterpretC h e new m a
-> m a
reinterpretViaHandler = coerce
{-# INLINE reinterpretViaHandler #-}
newtype ReinterpretSimpleC e new m a = ReinterpretSimpleC {
unReinterpretSimpleC :: IntroUnderC e new (InterpretSimpleC e m) a
}
deriving ( Functor, Applicative, Monad
, Alternative, MonadPlus
, MonadFix, MonadFail, MonadIO
, MonadThrow, MonadCatch, MonadMask
, MonadBase b, MonadBaseControl b
)
deriving MonadTrans via InterpretSimpleC e
deriving via IntroUnderC e new (InterpretSimpleC e m)
instance ( Threads (ReaderT (ReifiedHandler e m)) (Prims m)
, RepresentationalEff e
, KnownList new
, HeadEffs new m
, Carrier m
)
=> Carrier (ReinterpretSimpleC e new m)
reinterpretSimple :: forall e new m a p
. ( RepresentationalEff e
, KnownList new
, HeadEffs new m
, Threaders '[ReaderThreads] m p
)
=> EffHandler e m
-> ReinterpretSimpleC e new m a
-> m a
reinterpretSimple h =
interpretSimple h
.# introUnder
.# unReinterpretSimpleC
{-# INLINE reinterpretSimple #-}