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 _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe