[Haskell] Re: [Haskell-cafe] SimonPJ and Tim Harris explain STM -
haskell.org at liyang.hu
Thu Nov 23 17:42:57 EST 2006
On 23/11/06, Benjamin Franksen <benjamin.franksen at bessy.de> wrote:
> One answer is in fact "to make it so that Console.Write can be rolled back
> too". To achieve this one can factor the actual output to another task and
> inside the transaction merely send the message to a transactional channel
So, you could simply return the console output as (part of) the result
of the atomic action. Wrap it in a WriterT monad transformer, even.
(one, console) <- atomic $ runWriterT $ do
tell "hello world\n"
(Not terribly efficient, but you get the idea.)
You're just calculating what output to make inside the transaction;
the actual outputting happens outside, once the transaction commits.
> Another task regularly takes messages from the channel
With STM, the outputter task won't see any messages from the channel
until your main atomic block completes, after which you're living in
IO-land, so you might as well do the output yourself.
Pugs/Perl 6 takes the approach that any IO inside an atomic block
raises an exception.
> Unfortunately I can't see how to generalize this to input as well...
The dual of how you described the output situation: read a block of
input before the transaction starts, and consume this during the
transaction. I guess you're not seeing how this generalises because
potentially you won't know how much of the input you will need to read
beforehand... (so read all available input?(!) You have the dual
situation in the output case, in that you can't be sure how much
output it may generate / you will need to buffer.)
input <- hGetContent file
atomic $ flip runReaderT input $ do
input <- ask
-- do something with input
(This is actually a bad example, since hGetContents reads the file
lazily with interleaved IO...)
More information about the Haskell-Cafe