On Sat, Aug 30, 2008 at 02:30:42AM +0100, Ganesh Sittampalam wrote:
> Hi David,

Hi Ganesh!

> So the RIO type properly models this single-threadedness for the tentative 
> state, but not for the recorded or unrecorded state. It was the intuition 
> that any of these states could change that was behind the original 
> suggestion Jason mentioned that RIO should take two parameters of type 
> (RepoInState r u t) - the RepoInState type just serving to cut down the 
> number of direct parameters to RIO. Repository should just be Repository p 
> - the actual state it's in would be determined by the current RIO type 
> parameters.

The key is that there is only one function that changes the recorded state
(finalizeRepositoryChanges--which we might replace with withGutsOf or
something like that), and only one function that changes the unrecorded
state (applyToWorking), so it doesn't make much sense (to me) to put those
functions into the type witnesses.  Instead we can simply insist that they
are called no more than once per command.es a number of times for
efficiency reasons), but this is the goal that we should be working
towards.

As far as changes to working are concerned, we could of course perform then
whenever we like, but it's best practice to do all the in one fell swoop,
since changes to the working directory cannot be performed atomically, but
we'd like to perform them as atomically as possible.

With just a bit more work, we could pass more than one parameter to
withRepoLock, so as to enforce calling finalizeRepositoryChanges only once
per lock acquired (which is the real constraint--since you can't mix
witnesses from one withRepoLock to another).

A possible withRepoLock would be something like

withRepoLock :: (forall p C(r u). RepoPatch p =>
                 RIO p C(r u r) (SealedRIO p C(r u) (), Sealed (FL Prim C(u))))
             -> IO ()

which would first run the reading portion of the command (which can be
trivially interrupted with ctrl-C), followed by the tentative-updating
portion (which can be trivially interrupted unless we're using darcs-1
format), then would finalizeRepositoryChanges (which would no longer be
exported), and finally would update the working directory with the Prim
sequence returned.  This might be rather cumbersome to use, or might not.
But it's the kind of framework we'd want if we want the type system to
seriously prevent bugs.  We'd probably need some extra nuances in order to
do things like give appropriate error messages when we encounter an
exception while updating the working directory (e.g. when we tell people
they might be able to fix this with revert).

I hope this answers your question...

David
_______________________________________________
darcs-users mailing list
[email protected]
http://lists.osuosl.org/mailman/listinfo/darcs-users

Reply via email to