[Haskell-cafe] Caching the Result of a Transaction?
Matthew Brecknell
haskell at brecknell.org
Sat Apr 26 23:37:25 EDT 2008
Conal Elliott said:
> Can we implement a type 'TIVal a' (preferably without unsafePerformIO)
> with the following interface:
>
> newIVal :: STM (TIVal a, a -> STM ()) -- or IO (...)
> force :: TIVal a -> STM a
>
> instance Functor IVal
> instance Applicative IVal
> instance Monad IVal
>
> where
>
> * 'newIVal' makes something like an IVar that can be written/defined
> (just once) with the returned a->STM().
> * 'force' gets the value, retrying if not yet defined; once force is able
> to succeed, it always yields the same value.
> * 'fmap f tiv' becomes defined (force yields a value instead of retrying)
> when tiv does. Similarly for (<*>) and join.
> * Forcing 'fmap f tiv' more than once results in f being called only
> once,
> i.e., the result is cached and reused, as in pure values. Similarly for
> (<*>) and join.
Perhaps what you and Jake are looking for are fully-fledged "triggers"
on transactional memory. To solve the fmap problem, have each TIVar
backed by a separate TVar. Then the TIVar returned by fmap would act as
a cache for the original TIVar. A trigger would watch the TVar which
backs the original TIVar, updating the cache TVar when the original
TIVar is written. Nested fmaps would work simply as a cascade of
triggers.
The STM authors considered the possibility of triggers in their paper on
invariants [1], but instead took the safer option of read-only
invariants.
[1]http://research.microsoft.com/~simonpj/papers/stm/stm-invariants.pdf
More information about the Haskell-Cafe
mailing list