Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
This module provides DepT
, a monad transformer similar to ReaderT
.
The difference is that the environment of DepT
must be parameterized by
DepT
's own monad stack.
There's a function withDepT
which is analogous to withReaderT
.
There's no analogue of mapReaderT
however.
Synopsis
- newtype DepT (e_ :: (Type -> Type) -> Type) (m :: Type -> Type) (r :: Type) = DepT (ReaderT (e_ (DepT e_ m)) m r)
- runDepT :: DepT e_ m r -> e_ (DepT e_ m) -> m r
- toReaderT :: DepT e_ m r -> ReaderT (e_ (DepT e_ m)) m r
- withDepT :: forall small big m a. Monad m => (forall p q. (forall x. p x -> q x) -> small p -> small q) -> (forall t. big t -> small t) -> DepT small m a -> DepT big m a
- zoomEnv :: forall small big m a. Monad m => (forall p q. (forall x. p x -> q x) -> small p -> small q) -> (forall t. big t -> small t) -> small (DepT small m) -> small (DepT big m)
- data NilEnv m = NilEnv
- newtype Constant a (b :: k) = Constant {
- getConstant :: a
- module Control.Monad.Trans
- module Control.Monad.Dep.Class
- module Control.Monad.Reader.Class
The DepT transformer
newtype DepT (e_ :: (Type -> Type) -> Type) (m :: Type -> Type) (r :: Type) Source #
A monad transformer which adds a read-only environment to the given monad. The environment type must be parameterized with the transformer's stack.
The return
function ignores the environment, while >>=
passes the
inherited environment to both subcomputations.
Instances
MonadError e m => MonadError e (DepT e_ m) Source # | |
Defined in Control.Monad.Dep throwError :: e -> DepT e_ m a # catchError :: DepT e_ m a -> (e -> DepT e_ m a) -> DepT e_ m a # | |
MonadState s m => MonadState s (DepT e_ m) Source # | |
MonadWriter w m => MonadWriter w (DepT e_ m) Source # | |
MonadTrans (DepT e_) Source # | |
Defined in Control.Monad.Dep | |
Monad m => MonadReader (e_ (DepT e_ m)) (DepT e_ m) Source # | |
MonadFail m => MonadFail (DepT e_ m) Source # | |
Defined in Control.Monad.Dep | |
MonadFix m => MonadFix (DepT e_ m) Source # | |
Defined in Control.Monad.Dep | |
MonadIO m => MonadIO (DepT e_ m) Source # | |
Defined in Control.Monad.Dep | |
MonadZip m => MonadZip (DepT e_ m) Source # | |
Alternative m => Alternative (DepT e_ m) Source # | |
Applicative m => Applicative (DepT e_ m) Source # | |
Functor m => Functor (DepT e_ m) Source # | |
Monad m => Monad (DepT e_ m) Source # | |
MonadPlus m => MonadPlus (DepT e_ m) Source # | |
MonadCont m => MonadCont (DepT e_ m) Source # | |
MonadUnliftIO m => MonadUnliftIO (DepT e_ m) Source # | |
Defined in Control.Monad.Dep | |
Monad m => LiftDep (DepT e_ m) (DepT e_ m) Source # |
|
(Monad m, Coercible newtyped (e_ (DepT e_ m))) => LiftDep (DepT e_ m) (ReaderT newtyped m) Source # |
This can be useful to "deceive" a function into using an environment possessing different instances than the instances seen by the function's dependencies. |
runDepT :: DepT e_ m r -> e_ (DepT e_ m) -> m r Source #
Runs a DepT
action in an environment.
>>>
runDepT (pure "foo") NilEnv
"foo"
For more sophisticated invocation functions, see runFinalDepT
and runFromEnv
from dep-t-advice.
:: forall small big m a. Monad m | |
=> (forall p q. (forall x. p x -> q x) -> small p -> small q) | rank-2 map function |
-> (forall t. big t -> small t) | get a small environment from a big one |
-> DepT small m a | |
-> DepT big m a |
Changes the environment of a DepT
, for example making the DepT
work in
a "bigger" environment than the one in which was defined initially.
The scary first parameter is a function that, given a natural transformation of monads, changes the monad parameter of the environment record. This function can be defined manually for each environment record, or it can be generated using TH from the rank2classes package.
:: forall small big m a. Monad m | |
=> (forall p q. (forall x. p x -> q x) -> small p -> small q) | rank-2 map function |
-> (forall t. big t -> small t) | get a small environment from a big one |
-> small (DepT small m) | |
-> small (DepT big m) |
Makes the functions inside a small environment require a bigger environment.
The scary first parameter is a function that, given a natural transformation of monads, changes the monad parameter of the environment record. This function can be defined manually for each environment record, or it can be generated using TH from the rank2classes package.
zoomEnv
can be useful if we are encasing some preexisting small environment as a field of
a big environment, in order to make the types match:
>>>
:{
type Env :: (Type -> Type) -> Type data Env m = Env { _logger :: String -> m (), _repository :: Int -> m (), _controller :: Int -> m String } $(Rank2.TH.deriveFunctor ''Env) env :: Env (DepT Env IO) env = Env { _logger = \_ -> pure (), _repository = \_ -> pure (), _controller = \_ -> pure "foo" } type BiggerEnv :: (Type -> Type) -> Type data BiggerEnv m = BiggerEnv { _inner :: Env m, _extra :: Int -> m Int } biggerEnv :: BiggerEnv (DepT BiggerEnv IO) biggerEnv = BiggerEnv { _inner = zoomEnv (Rank2.<$>) _inner env, _extra = pure } :}
However, this is only needed when the monad of the smaller environment
is already "fixed" before inserting it in the bigger one—which I expect
to be an infrequent case. When the concrete monad is selected after nesting
the environments, zoomEnv
shouldn't be necessary.
The simplest environment
An empty environment that carries no functions, analogous to ()
for ReaderT
.
The next simplest environment
Constant
, which has a phantom type parameter, is a valid environment for
DepT
.
DepT (Constant e) m
makes DepT
behave similarly to ReaderT e m
,
in that the environment e
is independent of the monad.
Constant functor.
Constant | |
|
Instances
Re-exports
module Control.Monad.Trans
module Control.Monad.Dep.Class
module Control.Monad.Reader.Class