
I would like to be able to semi-permanently redirect stdout particularly. That is, say something like:
main = do h <- openFile "myoutput" WriteMode setStdOut h ..crux of the program.. hClose h
where any call which uses stdout either explicitly or implicitly (through putStr and the like) is redirecto to h.
I didn't see anything of this sort in either the std libs IO or in the GHC.IO/IOBase modules...would such a thingbe possible?
Yes, it is entirely possible to do this, and in fact we used to have such a thing (withStdout, withStderr) which got dropped when I re-implemented the I/O system. It's not immediately clear what the interface should be, though. If we have setStdout :: Handle -> IO () what happens to the original handle? It's unfortunately not possible to make stdout then be equal (in the == sense) to the handle passed in, although stdout would from then on behave like the other handle. Since in Haskell it is illegal to have two handles that refer to the same file, without the handles being equal, the original handle would have to be closed. Also there's a slight complication caused by GHC's representation of handles. Some handles have two independent "sides" to cope with the fact that a read/write stream (eg. a socket) needs two separate buffers. It wouldn't be possible to do setStdout with a stream-type Handle (or perhaps you just get the output side of the stream Handle). Cheers, Simon

Simon,
Yes, it is entirely possible to do this, and in fact we used to have such a thing (withStdout, withStderr) which got dropped when I
I assume these functions had type 'Handle -> IO a -> IO a' or something similar, where the original meaning of stdout, etc., was restored after the completion of the passed IO action? For me, this would actually be better, or at least equivalent.
re-implemented the I/O system. It's not immediately clear what the interface should be, though. If we have
setStdout :: Handle -> IO ()
what happens to the original handle?
I assumed, before looking at the GHC sources, that there were references stdinR/stdoutR which were IORef Handles and these were unsafely read by stdin and stdout (unsafely = safely because they are set at the beginning of execution, blah blah). Of course this turns out to not be the case, but the case is not completely dissimilar. Anyway, it seems something like withStdout, etc., is possible in the current scheme and this is enough for me. Is there any chance this will be possible in 5.04.1, the point about equality and two-sided handles not withstanding? - Hal

Yes, it is entirely possible to do this, and in fact we used to have such a thing (withStdout, withStderr) which got dropped when I re-implemented the I/O system. It's not immediately clear what the interface should be, though. If we have
setStdout :: Handle -> IO ()
what happens to the original handle?
A pattern common in the Win32 GDI is to use a type like: setStdout :: Handle -> IO Handle Which makes it easy to implement things like: withStdout :: Handle -> IO a -> IO a withStdout h m = do h' <- setStdout h m setStdout h' At some point, it might also be useful to introduce a notion of processes to GHC in addition to its current notion of threads. What I mean by this is: - with threads, you have independent execution of code but all threads see the same global environment. That is, stdout is the same for all of them. - with processes, you have independent execution but each process sees a different global environment. That is, processes can have different notions of stdout. Perhaps this is best done using implicit parameters though? We could bundle up all those environmental things (getArgs, stdout, etc.) in a record and pass it around... -- Alastair Reid alastair@reid-consulting-uk.ltd.uk Reid Consulting (UK) Limited http://www.reid-consulting-uk.ltd.uk/alastair/
participants (3)
-
Alastair Reid
-
Hal Daume III
-
Simon Marlow