re-opening a closed stdin?

Simon Marlow simonmar@microsoft.com
Mon, 25 Nov 2002 17:00:07 -0000


> Simon Marlow wrote:
>=20
> > > Simon Marlow:
> > > > [Lazy I/O] is nice, but it introduces too many problems.  What
> > > > happens to any I/O errors encountered by the lazy I/O? =20
> They have to
> > > > be discarded, which means you can't effectively use lazy I/O for
> > > > robust applications anyway.
> > >
> > > Surely they are thrown as exceptions which can then be manipulated
> > > in pure code using
> > >
> > >   mapExceptions :: (Exception -> Exception) -> (a -> a)
> > >
> > > and caught in the IO monad using catch?
> >
> > No, the report clearly states that they are discarded.
>=20
> Could you please point out where?  I couldn't find it with a=20
> quick look.

Section 11.2.1 in the Library Report, last paragraph.

> > We could perhaps have our own versions of the lazy I/O=20
> operations which
> > throw exceptions, but this in itself is problematic because=20
> these kind
> > of exceptions would be asynchronous in nature.  If lazy I/O=20
> is allowed
> > to raise exceptions, then we have a situation where=20
> evaluating anything
> > can raise an I/O exception.  In theory this shouldn't be a=20
> problem - we
> > all ought to be writing asynchronous-excpetion-safe code anyway to
> > protect against StackOverflow, but an I/O exception is=20
> often one that
> > you want to handle gracefully and recover from.  I feel distinctly
> > uncomfortable about I/O exceptions being thrown by pure=20
> code, and even
> > more uncomfortable about asynchronous I/O exceptions.
>=20
> Is even the following example from the library report (section 11.8.2)
> problematic?
>=20
> import System
> import Char( toUpper )
>=20
> main =3D do
>          [f1,f2] <- getArgs
>          s <- readFile f1
>          writeFile f2 (map toUpper s)

It depends what you want to happen in the event of a I/O error in the
file being read.  If you want to reliably clean up, say remove f2 and
emit a helpful message, then as Haskell 98 stands you can't do it.

If we were to make the lazy I/O raise an exception in the event of an
error, then you can do the cleanup, but you have to know which
computations can force the lazy I/O and wrap appropriate exception
handlers around them.  Knowing which computations can force the I/O is
problematic.

There *is* a reasonable semantics for readFile: read the whole file
immediately.  You don't have to generate the Haskell String eagerly,
just read the whole file into a cache and report any I/O errors.  This
doesn't work too well for large files, or for using readFile/getContents
to write stream processors though.

Cheers,
	Simon