{- | An effect providing access to an immutable (but locally-modifiable) context value.

This effect is similar to the traditional @MonadReader@ typeclass, though it allows the presence of multiple @Reader t@ effects.

Predefined carriers:

* "Control.Carrier.Reader".
* "Control.Monad.Trans.Reader".
* "Control.Monad.Trans.RWS.Lazy"
* "Control.Monad.Trans.RWS.Strict"
* If 'Reader' @r@ is the last effect in a stack, it can be interpreted directly to @(-> r)@ (a function taking an @r@).

@since 0.1.0.0
-}

module Control.Effect.Reader
( -- * Reader effect
  Reader(..)
, ask
, asks
, local
  -- * Re-exports
, Algebra
, Has
, run
) where

import Control.Algebra
import Control.Effect.Reader.Internal (Reader(..))

-- | Retrieve the environment value.
--
-- @
-- runReader a ('ask' '>>=' k) = runReader a (k a)
-- @
--
-- @since 0.1.0.0
ask :: Has (Reader r) sig m => m r
ask :: forall r (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader r) sig m =>
m r
ask = forall (eff :: (* -> *) -> * -> *) (sig :: (* -> *) -> * -> *)
       (m :: * -> *) a.
(Member eff sig, Algebra sig m) =>
eff m a -> m a
send forall r (m :: * -> *). Reader r m r
Ask
{-# INLINE ask #-}

-- | Project a function out of the current environment value.
--
-- @
-- 'asks' f = 'fmap' f 'ask'
-- @
--
-- @since 0.1.0.0
asks :: Has (Reader r) sig m => (r -> a) -> m a
asks :: forall r (sig :: (* -> *) -> * -> *) (m :: * -> *) a.
Has (Reader r) sig m =>
(r -> a) -> m a
asks = (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` forall r (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader r) sig m =>
m r
ask)
{-# INLINE asks #-}

-- | Run a computation with an environment value locally modified by the passed function.
--
-- @
-- runReader a ('local' f m) = runReader (f a) m
-- @
--
-- @since 0.1.0.0
local :: Has (Reader r) sig m => (r -> r) -> m a -> m a
local :: forall r (sig :: (* -> *) -> * -> *) (m :: * -> *) a.
Has (Reader r) sig m =>
(r -> r) -> m a -> m a
local r -> r
f m a
m = forall (eff :: (* -> *) -> * -> *) (sig :: (* -> *) -> * -> *)
       (m :: * -> *) a.
(Member eff sig, Algebra sig m) =>
eff m a -> m a
send (forall r (m :: * -> *) a. (r -> r) -> m a -> Reader r m a
Local r -> r
f m a
m)
{-# INLINE local #-}