Open andorp opened 8 years ago
I would like to implement this change.
What impact would this have to the interfaces? I used to be in favor of a change to help pass the current user around but not anymore. For the currentUserAddDb
solves this already.So I'd like to understand better what you are aiming to solve.
I've encountered use cases of the current user as a parameter for the persistent layer.
currentUserAddDb
functionmodifyDB
should record the user who touched the dataI actually think we should have a PersistCtx
that provides more than the user id. We also need a system time and a pure source of passwords. This is true at least in #333, but I suspect it also holds for any other working solution, even #328 once it's fixed.
Updated last comment: source of password should be an explicit argument, of course.
@np: could we argue about this some more? you said that understanding currentUserAddDb
may help me to like it. Here is a point that @andorp makes: it's not compositional.
Consider two transactions, AddIdea
and VoteOnIdea
for the former. They can be easily melted into a new transaction AddAndVoteOnIdea
, but the type of the new transaction will not match the one needed by currentUserAddDb
. So we need a new wrapper.
Have you thought of a solution for this? (We don't need to solve this before #340 has landed, and maybe not this month. But it can't hurt to talk about it now that the experience is fresh.)
An easy workaround for this is to create a similar function to addWithUser
which has the following type:
modifiesWithUser :: ... -> (User -> AUpdate a) -> m a
and something similar to
currentUserModifiesDB :: ... (User -> AUpdate a) -> m a
Which is kind of half way between the reader monad and the current solution and it does not involves TemplateHaskell magic, but it has the same functionality.
I was indeed expecting new wrappers such as the two proposed by @andorp. However one might need at least one more to combine two updates into one. I think that this is the simplest solution.
I'm also seeing a potential monad Reader
solution. For instance addIdea
has type AddDb Idea
which means: EnvWithProto Idea -> AUpdate ()
, it could have type: Proto Idea -> Reader Env (AUpdate ())
.
Of course we would give a name to Reader Env (AUpdate ())
, the template haskell module would have to use runReader
to expose Proto Idea -> Env -> AUpdate ()
to the acid-state layer. In a way this is to say, I think I do the change I tried yesterday (not the impossible one) but hey, I've failed before on that so...
If you feel so to try that implementation it is good for me. But I would be totally happy with the User -> AUpdate a
version, as we have to use only in few places.
I'd be fine with User -> AUpdate a
, as well, but that's just my personal preference for KISS (in this case, avoiding premature refactorings), even at the price of more verbose calls.
Instead of passing the current user around for
addDB
,modifyDB
, we could turn persistNat to a function that produces a natural transformation. Please take a look on the following snippet.What do you think?