[Haskell-cafe] [ANN] Safe Lazy IO in Haskell

nicolas.pouillard nicolas.pouillard at gmail.com
Sun Mar 22 18:28:35 EDT 2009

Excerpts from Henning Thielemann's message of Sun Mar 22 22:52:48 +0100 2009:
> On Sun, 22 Mar 2009, nicolas.pouillard wrote:
> > Excerpts from Henning Thielemann's message of Sat Mar 21 22:27:08 +0100 2009:
> >>
> >> Maybe you know of my packages lazy-io and explicit-exception which also
> >> aim at lazy I/O and asynchronous exception handling.
> >
> > I was indeed aware of these two packages but I think they hold orthogonal
> > ideas.
> >
> > About the lazy-io package, as explained in the documentation one has to
> > carefully choose which operations can be lifted. In safe-lazy-io I try
> > to choose a set of well behaving combinators to replace 'getContents' in the
> > IO monad.
> >
> > Moreover if I take the three problems of standard lazy IO in turn:
> > 1/ Control of resources: One advantage over standard lazy IO is that
> >   the file opening can also be done lazily, avoiding an immediate
> >   resource exhaustion. However one still relies on evaluation and garbage
> >   collection to take care of closing handles, which is not satisfying since
> >   handles are scarce resources.
> > 2/ Control of exceptions: If one writes a 'getContents' function such that
> >   it no longer hides I/O errors during reading, how do you guarantee
> >   that exceptions will happen during the LazyIO.run and not after?
> Currently I cannot guarantee anything. However my idea is to stay away 
> from built-in exceptions in IO. In explicit-exception there is an 
> experimental hidden module which provides an IO monad wrapper called SIO 
> which cannot throw any IO exception.
>    http://code.haskell.org/explicit-exception/src/System/IO/Straight.hs
>   Actually, I think it's the wrong way round to build an exception-free 
> monad on top of one with exceptions. Instead IO should be built on top of 
> SIO, but that's not possible for historical reasons.
>   The only safe operation to get into SIO is
>    ioToExceptionalSIO :: IO a -> ExceptionalT IOException SIO a
>   That is, it makes exceptions explicit and SIO operations can never throw 
> IO exceptions. You should convert synchronous explicit exceptions of 
> atomic operations like getChar into asynchronous explicit exceptions, 
> combine them lazily to big operations like getContents. Then you get
>    getContents :: SIO (Asynchronous.Exception IOException String)
>   If you run lazy SIO operations you can't become surprised by exceptions.

It sounds like a nice idea, it would be great to have a straight-io package
to play a bit more with explicit exceptions in things like 'IO'.

For safe-lazy-io I wanted to keep the exception management as light as
possible. In particular when writing programs where most of the 'IO' errors
are considered fatals---EOF is not fatal of course but using getContents one
do not see it.

> > 3/ Determinism: when freely combining multiple inputs one risks the problem
> >   mentioned by Oleg [1], when using your package it will depend on
> >   the 'getContents' function we use:
> >   a) if we 'liftIO' the standard 'getContents' function, we can have the issue.
> >   b) if we write a new 'getContents' as below [2], then (if I got right
> >      your lazy IO monad) all reads are chained. And then one has
> >      to process inputs in the same order.
> I wouldn't build hClose into getContents, because you never know, whether 
> the file is read until it's end. If you call a LazyIO.getContents twice, 
> the contents are read sequential. In order to read file contents 
> simultaneously you must call (LazyIO.run LazyIO.getContents) twice in the 
> IO monad.

Right but one of the purposes of safe-lazy-io is to provides a good
management of file handles in particular closing them. Actually the
implementation of lazy inputs focus particularly on that---through the
'Finalized' values.


Nicolas Pouillard

More information about the Haskell-Cafe mailing list