module Control.Effect.Reader ( -- * Effects Ask(..) , Local(..) , Reader -- * Actions , ask , asks , local -- * Interpretations , runAskConst , runAskAction , askToAsk , runReader -- * Simple variants , runAskConstSimple , runAskActionSimple , askToAskSimple -- * Threading constraints , ReaderThreads -- * Carriers , ReaderC ) where import Control.Effect import Control.Effect.Internal.Reader import Control.Monad.Trans.Reader (ReaderT(..)) ask :: Eff (Ask i) m => m i ask = send Ask {-# INLINE ask #-} asks :: Eff (Ask i) m => (i -> a) -> m a asks = (<$> ask) {-# INLINE asks #-} local :: Eff (Local i) m => (i -> i) -> m a -> m a local f m = send (Local f m) {-# INLINE local #-} -- | Run connected @'Ask' i@ and @'Local' i@ effects -- i.e. @'Reader' i@. -- -- @'Derivs' ('ReaderC' i m) = 'Local' i ': 'Ask' i ': 'Derivs' m@ -- -- @'Control.Effect.Carrier.Prims' ('ReaderC' i m) = 'Control.Effect.Type.ReaderPrim.ReaderPrim' i ': 'Control.Effect.Carrier.Prims' m@ runReader :: forall i m a p . ( Carrier m , Threaders '[ReaderThreads] m p ) => i -> ReaderC i m a -> m a runReader i m = runReaderT (unReaderC m) i {-# INLINE runReader #-} -- | Run an 'Ask' effect by providing a constant to be given -- at each use of 'ask'. -- -- This has a higher-rank type, as it makes use of 'InterpretReifiedC'. -- __This makes 'runAskConst' very difficult to use partially applied.__ -- __In particular, it can't be composed using @'.'@.__ -- -- If performance is secondary, consider using the slower 'runAskConstSimple', -- which doesn't have a higher-rank type. runAskConst :: forall i m a . Carrier m => i -> InterpretReifiedC (Ask i) m a -> m a runAskConst i = interpret $ \case Ask -> return i {-# INLINE runAskConst #-} -- | Run an 'Ask' effect by providing an action to be executed -- at each use of 'ask'. -- -- This has a higher-rank type, as it makes use of 'InterpretReifiedC'. -- __This makes 'runAskAction' very difficult to use partially applied.__ -- __In particular, it can't be composed using @'.'@.__ -- -- If performance is secondary, consider using the slower 'runAskActionSimple', -- which doesn't have a higher-rank type. runAskAction :: forall i m a . Carrier m => m i -> InterpretReifiedC (Ask i) m a -> m a runAskAction m = interpret $ \case Ask -> liftBase m {-# INLINE runAskAction #-} -- | Transform an @'Ask' i@ effect into an @'Ask' j@ effect by -- providing a function to convert @j@ to @i@. -- -- This has a higher-rank type, as it makes use of 'InterpretReifiedC'. -- __This makes 'askToAsk' very difficult to use partially applied.__ -- __In particular, it can't be composed using @'.'@.__ -- -- If performance is secondary, consider using the slower 'askToAskSimple', -- which doesn't have a higher-rank type. askToAsk :: forall i j m a . Eff (Ask j) m => (j -> i) -> InterpretReifiedC (Ask i) m a -> m a askToAsk f = interpret $ \case Ask -> asks f {-# INLINE askToAsk #-} -- | Run an 'Ask' effect by providing a constant to be given -- at each use of 'ask' -- -- This is a less performant version of 'runAskConst' that doesn't have -- a higher-rank type, making it much easier to use partially applied. runAskConstSimple :: forall i m a p . ( Carrier m , Threaders '[ReaderThreads] m p ) => i -> InterpretSimpleC (Ask i) m a -> m a runAskConstSimple i = interpretSimple $ \case Ask -> return i {-# INLINE runAskConstSimple #-} -- | Run an 'Ask' effect by providing an action to be executed -- at each use of 'ask'. -- -- This is a less performant version of 'runAskAction' that doesn't have -- a higher-rank type, making it much easier to use partially applied. runAskActionSimple :: forall i m a p . ( Carrier m , Threaders '[ReaderThreads] m p ) => m i -> InterpretSimpleC (Ask i) m a -> m a runAskActionSimple mi = interpretSimple $ \case Ask -> liftBase mi {-# INLINE runAskActionSimple #-} -- | Transform an @'Ask' i@ effect into an @'Ask' j@ effect by -- providing a function to convert @j@ to @i@. -- -- This is a less performant version of 'askToAsk' that doesn't have -- a higher-rank type, making it much easier to use partially applied. askToAskSimple :: forall i j m a p . ( Eff (Ask j) m , Threaders '[ReaderThreads] m p ) => (j -> i) -> InterpretSimpleC (Ask i) m a -> m a askToAskSimple f = interpretSimple $ \case Ask -> asks f {-# INLINE askToAskSimple #-}