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

nicolas.pouillard nicolas.pouillard at gmail.com
Sun Mar 22 13:51:11 EDT 2009

Excerpts from Henning Thielemann's message of Sat Mar 21 22:27:08 +0100 2009:
> On Fri, 20 Mar 2009, Nicolas Pouillard wrote:
> > Hi folks,
> >
> > We have good news (nevertheless we hope) for all the lazy guys standing there.
> > Since their birth, lazy IOs have been a great way to modularly leverage all the
> > good things we have with *pure*, *lazy*, *Haskell* functions to the real world
> > of files.
> 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

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?
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.

However I've found the underlying idea of your monad brilliant. I've tried
a little to use something similar as a base for the implementation but didn't

> With lazy-io, you are 
> able to write more complicated things than getContents. I needed this for 
> HTTP communication that is run by demand. That is when the HTTP response 
> header is requested, then the function could send a HTTP request first. Is 
> it possible and sensible to combine this with safe-lazy-io?

While currently focusing only on reading file handles, the long term purpose
for this technique is to have new primitives like reading on sockets, using

> I have also code that demonstrates the usage of explicit asynchronous 
> exceptions. I have however still not a set of combinators that makes 
> working with asynchronous exceptions as simple as working with synchronous 
> ones:
>   http://hackage.haskell.org/cgi-bin/hackage-scripts/package/spreadsheet

I also think that explicit asynchronous exceptions could be part of the equation,
however I currently don't know how to mix them well.

Best regards,

[1]: http://www.haskell.org/pipermail/haskell/2009-March/021064.html
  hGetContents :: Handle -> LIO.T String
  hGetContents h = lazyRead
    where lazyRead = do
            isEOF <- liftIO $ hIsEOF h
            if isEOF
              then do
                unit <- liftIO $ hClose h
                return $ unit `seq` []
              else do
                c     <- liftIO $ hGetChar h
                cs    <- lazyRead
                return $ c : cs

Nicolas Pouillard

More information about the Haskell-Cafe mailing list