packages feed

dep-t 0.1.0.0 → 0.1.0.1

raw patch · 5 files changed

+36/−7 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for dep-t +## 0.1.0.1 ++* Minor documentation changes.+ ## 0.1.0.0 -- YYYY-mm-dd  * First version. Released on an unsuspecting world.
README.md view
@@ -10,7 +10,7 @@ ## Rationale  To achieve dependency injection in Haskell, a common solution is to build a-record of functions and pass it to the program logic some variant of+record of functions and pass it to the program logic using some variant of [`ReaderT`](http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Reader.html).  Let's start by defining some auxiliary typeclasses to extract functions from an@@ -46,8 +46,8 @@  Here's a function which obtains its dependencies from the environment record: -    _mkControllerIO :: (HasLogger e IO, HasRepository e IO) => Int -> ReaderT e IO Int-    _mkControllerIO x = do+    mkControllerIO :: (HasLogger e IO, HasRepository e IO) => Int -> ReaderT e IO Int+    mkControllerIO x = do       doLog <- asks logger       liftIO $ doLog "I'm going to insert in the db!"       insert <- asks repository@@ -169,6 +169,24 @@ collecting the outputs of functions working as ["test doubles"](https://martinfowler.com/bliki/TestDouble.html). +## Invoking the functions in the environment is cumbersome++Yeah, it's annoying to perform the "ask for function, invoke function" dance each time:++    mkController x = do+      doLog <- asks logger+      doLog "I'm going to insert in the db!"++One workaround (at the cost of more boilerplate) is to define helper functions like:  ++    logger' :: (MonadReader e m, HasLogger e m) => String -> m ()+    logger' msg = asks logger >>= \f -> f msg++Which you can invoke like this:++    mkController x = do+      logger' "I'm going to insert in the db!"+ ## Caveats  The structure of the `DepT` type might be prone to trigger a [known infelicity@@ -181,6 +199,10 @@   question](https://stackoverflow.com/a/61782258/1364288).  - The implementation of `mapDepT` was teased out in [this other SO question](https://stackoverflow.com/questions/65710657/writing-a-zooming-function-for-a-readert-like-monad-transformer).++- An [SO+  answer](https://stackoverflow.com/questions/57703898/how-to-call-impure-functions-from-pure-ones/57714058#57714058)+  about records-of-functions and the "veil of polymorphism".  - I'm unsure of the relationship between `DepT` and the technique described in   [Adventures assembling records of
dep-t.cabal view
@@ -1,7 +1,7 @@ cabal-version:       3.0  name:                dep-t-version:             0.1.0.0+version:             0.1.0.1 synopsis:            Reader-like monad transformer for dependency injection. description:         Put all your functions in the environment record! Let all                      your functions read from the environment record! No favorites!
lib/Control/Monad/Dep.hs view
@@ -121,7 +121,7 @@ --    Makes the functions inside a small environment require a bigger environment. -- --    This can be useful if we are encasing the small environment as a field of---    the big environment, ir order to make the types match.+--    the big environment, in order to make the types match. -- --    The scary first parameter is a function that, given a natural --    transformation of monads, changes the monad parameter of the environment
test/tests.hs view
@@ -29,6 +29,9 @@ class HasLogger r m | r -> m where   logger :: r -> String -> m () +logger' :: (MonadReader e m, HasLogger e m) => String -> m ()+logger' msg = asks logger >>= \f -> f msg+ type HasRepository :: Type -> (Type -> Type) -> Constraint class HasRepository r m | r -> m where   repository :: r -> Int -> m ()@@ -98,8 +101,8 @@ -- In a sufficiently complex app, the diverse functions will form a DAG of -- dependencies between each other. So it would be nice if the functions were -- treated uniformly, all having access to (views of) the environment record.-_mkControllerIO :: (HasLogger e IO, HasRepository e IO) => Int -> ReaderT e IO Int-_mkControllerIO x = do+mkControllerIO :: (HasLogger e IO, HasRepository e IO) => Int -> ReaderT e IO Int+mkControllerIO x = do   doLog <- asks logger   liftIO $ doLog "I'm going to insert in the db!"   insert <- asks repository