dep-t-0.6.0.0: Dependency injection for records-of-functions.
Safe HaskellNone
LanguageHaskell2010

Control.Monad.Dep

Description

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

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.

Constructors

DepT (ReaderT (e_ (DepT e_ m)) m r) 

Instances

Instances details
MonadWriter w m => MonadWriter w (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

writer :: (a, w) -> DepT e_ m a #

tell :: w -> DepT e_ m () #

listen :: DepT e_ m a -> DepT e_ m (a, w) #

pass :: DepT e_ m (a, w -> w) -> DepT e_ m a #

MonadState s m => MonadState s (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

get :: DepT e_ m s #

put :: s -> DepT e_ m () #

state :: (s -> (a, s)) -> DepT e_ m a #

MonadError e m => MonadError e (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

throwError :: e -> DepT e_ m a #

catchError :: DepT e_ m a -> (e -> DepT e_ m a) -> DepT e_ m a #

MonadTrans (DepT e_) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

lift :: Monad m => m a -> DepT e_ m a #

Monad m => MonadReader (e_ (DepT e_ m)) (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

ask :: DepT e_ m (e_ (DepT e_ m)) #

local :: (e_ (DepT e_ m) -> e_ (DepT e_ m)) -> DepT e_ m a -> DepT e_ m a #

reader :: (e_ (DepT e_ m) -> a) -> DepT e_ m a #

Monad m => Monad (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

(>>=) :: DepT e_ m a -> (a -> DepT e_ m b) -> DepT e_ m b #

(>>) :: DepT e_ m a -> DepT e_ m b -> DepT e_ m b #

return :: a -> DepT e_ m a #

Functor m => Functor (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

fmap :: (a -> b) -> DepT e_ m a -> DepT e_ m b #

(<$) :: a -> DepT e_ m b -> DepT e_ m a #

MonadFix m => MonadFix (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

mfix :: (a -> DepT e_ m a) -> DepT e_ m a #

MonadFail m => MonadFail (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

fail :: String -> DepT e_ m a #

Applicative m => Applicative (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

pure :: a -> DepT e_ m a #

(<*>) :: DepT e_ m (a -> b) -> DepT e_ m a -> DepT e_ m b #

liftA2 :: (a -> b -> c) -> DepT e_ m a -> DepT e_ m b -> DepT e_ m c #

(*>) :: DepT e_ m a -> DepT e_ m b -> DepT e_ m b #

(<*) :: DepT e_ m a -> DepT e_ m b -> DepT e_ m a #

MonadZip m => MonadZip (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

mzip :: DepT e_ m a -> DepT e_ m b -> DepT e_ m (a, b) #

mzipWith :: (a -> b -> c) -> DepT e_ m a -> DepT e_ m b -> DepT e_ m c #

munzip :: DepT e_ m (a, b) -> (DepT e_ m a, DepT e_ m b) #

MonadIO m => MonadIO (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

liftIO :: IO a -> DepT e_ m a #

Alternative m => Alternative (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

empty :: DepT e_ m a #

(<|>) :: DepT e_ m a -> DepT e_ m a -> DepT e_ m a #

some :: DepT e_ m a -> DepT e_ m [a] #

many :: DepT e_ m a -> DepT e_ m [a] #

MonadPlus m => MonadPlus (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

mzero :: DepT e_ m a #

mplus :: DepT e_ m a -> DepT e_ m a -> DepT e_ m a #

MonadCont m => MonadCont (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

callCC :: ((a -> DepT e_ m b) -> DepT e_ m a) -> DepT e_ m a #

MonadUnliftIO m => MonadUnliftIO (DepT e_ m) Source # 
Instance details

Defined in Control.Monad.Dep

Methods

withRunInIO :: ((forall a. DepT e_ m a -> IO a) -> IO b) -> DepT e_ m b #

Monad m => LiftDep (DepT e_ m) (DepT e_ m) Source #

DepT can be d-lifted to itself.

Instance details

Defined in Control.Monad.Dep

Methods

liftD :: DepT e_ m x -> DepT e_ m x Source #

(Monad m, Coercible newtyped (e_ (DepT e_ m))) => LiftDep (DepT e_ m) (ReaderT newtyped m) Source #

DepT can be d-lifted to a ReaderT in which the environment record containing further DepT actions has been hidden behind a newtype.

This can be useful to "deceive" a function into using an environment possessing different instances than the instances seen by the function's dependencies.

Instance details

Defined in Control.Monad.Dep

Methods

liftD :: DepT e_ m x -> ReaderT newtyped m x Source #

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.

toReaderT :: DepT e_ m r -> ReaderT (e_ (DepT e_ m)) m r Source #

withDepT Source #

Arguments

:: 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.

zoomEnv Source #

Arguments

:: 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

data NilEnv m Source #

An empty environment that carries no functions, analogous to () for ReaderT.

Constructors

NilEnv 

Re-exports