
Ryan Ingram wrote:
Consider the following transaction:
intV :: TVar Int boolV :: TVar Bool
interesting = atomically $ do retryUntil intV (> 50) retryUntil boolV id
Lets say that intV contains 100 and boolV contains False. Then this transaction retries. Now, if intV changes to 101, this transaction doesn't need to re-run; we can see immediately that no predicate changed. Using "readTVarWhen", this is less clear; the transaction log would hold a read on intV which would be more difficult to ignore.
I don't quite understand what you want to do but I presume it's related to the following: given an expression like readTVar intV >>= (\ -> ... readTVar boolV >>= (\_ -> ... retry)) The ... indicate branches that are there have not been taken in our example run, so the STM-side-effects that have been performed are readTVar intV readTVar boolV retry The thread waits for either intV or boolV to change. Now, assume that boolV changes. Then, the idea for improving performance is to not restart the whole transaction, but only the part after the readTVar boolV . In other words, only the continuation (\_ -> ... retry) will be executed again (and possibly yield something different from retry ). I'm not sure whether this is currently implemented in Control.STM. It seems that your scheme wants even more. You want to avoid work when intV changes, because the predicate for boolV clearly indicates that no matter what intV is, we'll have to retry anyway. Unfortunately, I don't think it works: the predicate itself might depend on intV interesting = atomically $ readTVar intV >>= $ \i -> if i > 50 then retry else retryUntil boolV (even i ==) That's the general property of >>= , you always have to evaluate its right argument when the left argument changes. In essence, we have the same problem with parser combinators. Applicative functors to the rescue! Regards, apfelmus