{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses, RankNTypes, TypeOperators, UndecidableInstances #-}
module Control.Effect.Interpret
( runInterpret
, InterpretC(..)
, runInterpretState
, InterpretStateC(..)
) where
import Control.Applicative (Alternative(..))
import Control.Effect.Carrier
import Control.Effect.Reader
import Control.Effect.State
import Control.Monad (MonadPlus(..))
import Control.Monad.Fail
import Control.Monad.Fix
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
runInterpret :: (forall x . eff m x -> m x) -> InterpretC eff m a -> m a
runInterpret handler = runReader (Handler handler) . runInterpretC
newtype InterpretC eff m a = InterpretC { runInterpretC :: ReaderC (Handler eff m) m a }
deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus)
instance MonadTrans (InterpretC eff) where
lift = InterpretC . lift
{-# INLINE lift #-}
newtype Handler eff m = Handler (forall x . eff m x -> m x)
runHandler :: (HFunctor eff, Functor m) => Handler eff m -> eff (InterpretC eff m) a -> m a
runHandler h@(Handler handler) = handler . hmap (runReader h . runInterpretC)
instance (HFunctor eff, Carrier sig m) => Carrier (eff :+: sig) (InterpretC eff m) where
eff (L op) = do
handler <- InterpretC ask
lift (runHandler handler op)
eff (R other) = InterpretC (eff (R (handleCoercible other)))
{-# INLINE eff #-}
runInterpretState :: (forall x . s -> eff (StateC s m) x -> m (s, x)) -> s -> InterpretStateC eff s m a -> m (s, a)
runInterpretState handler state = runState state . runReader (HandlerState (\ eff -> StateC (\ s -> handler s eff))) . runInterpretStateC
newtype InterpretStateC eff s m a = InterpretStateC { runInterpretStateC :: ReaderC (HandlerState eff s m) (StateC s m) a }
deriving (Alternative, Applicative, Functor, Monad, MonadFail, MonadFix, MonadIO, MonadPlus)
instance MonadTrans (InterpretStateC eff s) where
lift = InterpretStateC . lift . lift
{-# INLINE lift #-}
newtype HandlerState eff s m = HandlerState (forall x . eff (StateC s m) x -> StateC s m x)
runHandlerState :: (HFunctor eff, Functor m) => HandlerState eff s m -> eff (InterpretStateC eff s m) a -> StateC s m a
runHandlerState h@(HandlerState handler) = handler . hmap (runReader h . runInterpretStateC)
instance (HFunctor eff, Carrier sig m, Effect sig) => Carrier (eff :+: sig) (InterpretStateC eff s m) where
eff (L op) = do
handler <- InterpretStateC ask
InterpretStateC (lift (runHandlerState handler op))
eff (R other) = InterpretStateC (eff (R (R (handleCoercible other))))
{-# INLINE eff #-}