| What you want is allowed. Although stdin *is* a constant, it's simply a
| constant that refers to a handle. The handle information (file pointer,
| attached device etc.) needn't be constant. It's entirely consistent to
| provide, say:
|
| reconnect :: Handle -> Handle -> IO Handle
|
| to connect one handle to the same device as another (as long as you're
| careful in the impl. about duplicating file pointers, which can get you into
| trouble -- new files are much easier to deal with!). This was actually one
| of the extensions that was considered fairly carefully in the I/O design.
This doesn't do what Sigbjorn is suggesting.
Suppose I import a module written by someone else which exports
the function toUpper:
-- toUpper reads stdin, converts all characters to upper
-- case, and sends them to stdout
toUpper :: IO ()
Now I import another module which exports sort:
-- sort reads stdin, divides it into lines, sorts the lines
-- and sends them to stdout
sort :: IO ()
Now suppose I want to arrange to connect toUpper and sort together.
I might hope to do it like this:
module Main where
import M1( toUpper )
import M2( sort )
main = do
(in,out) <- pipe;
forkIO (withStdOut in toUpper);
withStdIn out sort
The new functions are
pipe :: IO (Handle,Handle)
withStdOut, withStdIn :: Handle -> IO () -> IO ()
The point here is that toUpper and sort each work with *different* mappings
of stdin, stdout.
This example uses concurrency, which Haskell doesn't have.
In the absence of concurrency you can hack it like this:
main = do
(in,out) <- pipe;
old_stdout <- setStdOut in;
toUpper;
setStdOut old_stdout;
setStdIn out;
sort
But it's a hack, isn't it. And it doesn't extend to concurrency.
But this may help explain why I'm not so steamed up as I am about argv!
Simon