Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module provides definitions that let us translate record-of-functions code of the form:
>>>
:{
type HasLogger :: (Type -> Type) -> Type -> Constraint class HasLogger d e | e -> d where logger :: e -> String -> d () type HasRepository :: (Type -> Type) -> Type -> Constraint class HasRepository d e | e -> d where repository :: e -> Int -> d () mkControllerIO :: (HasLogger IO e, HasRepository IO e) => Int -> ReaderT e IO String mkControllerIO x = do e <- ask liftIO $ logger e "I'm going to insert in the db!" liftIO $ repository e x return "view" :}
into the more polymorphic form:
>>>
:{
mkController :: MonadDep [HasLogger, HasRepository] d e m => Int -> m String mkController x = do e <- ask liftD $ logger e "I'm going to insert in the db!" liftD $ repository e x return "view" :}
which can also be given the equivalent signature:
>>>
:{
mkController' :: (HasLogger d e, HasRepository d e, LiftDep d m, MonadReader e m) => Int -> m String mkController' = mkController :}
The new code can be used as a drop-in replacement of the old one:
>>>
:{
mkControllerIO' :: (HasLogger IO e, HasRepository IO e) => Int -> ReaderT e IO String mkControllerIO' = mkController' :}
Notice that in the new code effects taken from the environment record are
lifted using liftD
instead of lift
or liftIO
.
Reader-like monads carrying dependencies in their environment
type family MonadDep dependencies d e m where ... Source #
MonadDep
is not its own typeclass, but MonadReader
plus some supplementary constraints.
A MonadDep dependencies d e m
is a MonadReader e m
where the environment
e
provides some dependencies
with effects in the monad d
, additionally requiring that the
effects can be lifted back to the monad m
by using liftD
.
The dependencies
are specified as a type-level list of two-parameter
HasX
typeclasses. Those typeclasses should expect the effect monad
d
as its first parameter.
Writing code polymorphic over MonadDep
lets us execute it in both ReaderT
and DepT
contexts.
MonadDep '[] d e m = (LiftDep d m, MonadReader e m) | |
MonadDep (dependency ': dependencies) d e m = (dependency d e, MonadDep dependencies d e m) |
Lifting effects from dependencies
class Monad d => LiftDep d m where Source #
Auxiliary typeclass for monads that can be lifted to other monads.
Its intended use is lifting monadic actions found in some reader-like environment.
Note: The RIO
monad from rio could be
given a LiftDept IO RIO
instance; it's not done here to avoid increasing
the dependency footprint.
Instances
Monad m => LiftDep m (ReaderT e m) Source # | The simplest case: we can d-lift the base monad sitting just below a (Perhaps this could be extended to any monad transformer, but let's leave it simple for now.) |
Defined in Control.Monad.Dep.Class | |
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. |