module Control.Monad.Trans.Ether.Reader
(
Reader
, reader
, runReader
, ReaderT
, readerT
, runReaderT
, mapReaderT
, withReaderT
, ask
, local
, liftCatch
, liftCallCC
) where
import Data.Proxy (Proxy(Proxy))
import Data.Functor.Identity (Identity(..))
import Data.Coerce (coerce)
import Control.Applicative
import Control.Monad (MonadPlus)
import Control.Monad.Fix (MonadFix)
import Control.Monad.Trans.Class (MonadTrans, lift)
import Control.Monad.IO.Class (MonadIO)
import Control.Ether.Tagged (Taggable(..), Tagged(..))
import GHC.Generics (Generic)
import qualified Control.Newtype as NT
import qualified Control.Monad.Signatures as Sig
import qualified Control.Monad.Trans.Reader as Trans
import qualified Control.Monad.Cont.Class as Class
import qualified Control.Monad.Reader.Class as Class
import qualified Control.Monad.State.Class as Class
import qualified Control.Monad.Writer.Class as Class
import qualified Control.Monad.Error.Class as Class
type Reader tag r = ReaderT tag r Identity
newtype ReaderT tag r m a = ReaderT (Trans.ReaderT r m a)
deriving ( Generic
, Functor, Applicative, Alternative, Monad, MonadPlus
, MonadFix, MonadTrans, MonadIO )
instance NT.Newtype (ReaderT tag r m a)
instance Taggable (ReaderT tag r m) where
type Tag (ReaderT tag r m) = 'Just tag
type Inner (ReaderT tag r m) = 'Just m
instance Tagged (ReaderT tag r m) tag where
type Untagged (ReaderT tag r m) = Trans.ReaderT r m
readerT :: proxy tag -> (r -> m a) -> ReaderT tag r m a
readerT t = tagged t . Trans.ReaderT
reader :: Monad m => proxy tag -> (r -> a) -> ReaderT tag r m a
reader t = tagged t . Trans.reader
runReaderT :: proxy tag -> ReaderT tag r m a -> r -> m a
runReaderT t = Trans.runReaderT . untagged t
runReader :: proxy tag -> Reader tag r a -> r -> a
runReader t = Trans.runReader . untagged t
mapReaderT :: proxy tag -> (m a -> n b) -> ReaderT tag r m a -> ReaderT tag r n b
mapReaderT t f m = tagged t $ Trans.mapReaderT f (coerce m)
withReaderT
:: proxy tag
-> (r' -> r)
-> ReaderT tag r m a
-> ReaderT tag r' m a
withReaderT t f m = tagged t $ Trans.withReaderT f (coerce m)
liftCatch :: proxy tag -> Sig.Catch e m a -> Sig.Catch e (ReaderT tag r m) a
liftCatch t f m h = tagged t $ Trans.liftCatch f (coerce m) (coerce h)
liftCallCC :: proxy tag -> Sig.CallCC m a b -> Sig.CallCC (ReaderT tag r m) a b
liftCallCC t callCC f = tagged t $ Trans.liftCallCC callCC (coerce f)
ask :: Monad m => proxy tag -> ReaderT tag r m r
ask t = tagged t Trans.ask
local
:: proxy tag
-> (r -> r)
-> ReaderT tag r m a
-> ReaderT tag r m a
local = withReaderT
instance Class.MonadCont m => Class.MonadCont (ReaderT tag r m) where
callCC = liftCallCC Proxy Class.callCC
instance Class.MonadReader r' m => Class.MonadReader r' (ReaderT tag r m) where
ask = lift Class.ask
local = mapReaderT Proxy . Class.local
reader = lift . Class.reader
instance Class.MonadState s m => Class.MonadState s (ReaderT tag r m) where
get = lift Class.get
put = lift . Class.put
state = lift . Class.state
instance Class.MonadWriter w m => Class.MonadWriter w (ReaderT tag r m) where
writer = lift . Class.writer
tell = lift . Class.tell
listen = mapReaderT Proxy Class.listen
pass = mapReaderT Proxy Class.pass
instance Class.MonadError e m => Class.MonadError e (ReaderT tag r m) where
throwError = lift . Class.throwError
catchError = liftCatch Proxy Class.catchError