danidiaz / dep-t

Dependency injection for records-of-functions.
http://hackage.haskell.org/package/dep-t
BSD 3-Clause "New" or "Revised" License
8 stars 2 forks source link

Add a subcall-aware version of `local`. #3

Closed danidiaz closed 3 years ago

danidiaz commented 3 years ago

local for DepT will change the environment for an action and all of its sub-calls taken from the environment.

Perhaps it would be possible to have a version local that accepted two environment -> environment functions. One function would change the environment for the action, and the other would change the environment for its sub-calls (maybe undoing the earlier change).

Why have this? Well, perhaps it could be useful to have some piece of program logic that saw a modified version of the environment, but where its sub-calls saw the original environment unchanged. Like, a function that has a HasLogger constraint, but we want that function—and that function only—to use a secondary logger.

To implement this version of local, we would likely need a rank-2 mapping function on the environment, like zoomEnv does. And we would likely encounter the same problem with inlining as zoomEnv.

danidiaz commented 3 years ago

I didn't find how to do it for functions that have already "chosen" DepT as their effect monad.

But for functions polymorphic over the MonadDep constraint introduced in 4c3dc273823823f095ed8085e6f7ac71698b0fc8, we can use the trick of "solidifying" the monad to a ReaderT which uses a newtyped version of the environment, and then convert it to DepT.

This was implemented in the deceive function of the dep-t-advice pacakge.