Hi,

On 23/11/06, Benjamin Franksen <[EMAIL PROTECTED]> 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
(TChan):

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"
      return 1
  putStr console

(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
      return 42

(This is actually a bad example, since hGetContents reads the file
lazily with interleaved IO...)

later,
/Liyang
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to