{-# LANGUAGE DeriveFunctor, ExplicitForAll, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, RankNTypes, ScopedTypeVariables, TypeOperators, UndecidableInstances #-}
module Control.Effect.Interpose
( InterposeC (..)
, runInterpose
) where
import Control.Effect.Carrier
import Control.Effect.Reader
import Control.Effect.Sum
import Control.Monad.Trans.Class
runInterpose :: (forall x . eff m (m x) -> m x) -> InterposeC eff m a -> m a
runInterpose handler = runReader (Handler handler) . runInterposeC
newtype InterposeC eff m a = InterposeC { runInterposeC :: ReaderC (Handler eff m) m a }
deriving (Applicative, Functor, Monad)
instance MonadTrans (InterposeC eff) where
lift = InterposeC . lift
newtype Handler eff m = Handler (forall x . eff m (m x) -> m x)
runHandler :: HFunctor eff => Handler eff m -> eff (ReaderC (Handler eff m) m) (ReaderC (Handler eff m) m a) -> m a
runHandler h@(Handler handler) = handler . handlePure (runReader h)
instance (HFunctor eff, Carrier sig m, Member eff sig) => Carrier sig (InterposeC eff m) where
eff (op :: sig (InterposeC eff m) (InterposeC eff m a))
| Just (op' :: eff (InterposeC eff m) (InterposeC eff m a)) <- prj op = do
handler <- InterposeC ask
lift (runHandler handler (handleCoercible op'))
| otherwise = InterposeC (ReaderC (\ handler -> eff (handlePure (runReader handler . runInterposeC) op)))