Raw I/O library proposal, second (more pragmatic) draft

Simon Marlow simonmar@microsoft.com
Thu, 7 Aug 2003 10:13:12 +0100

> > fileRead    :: File -> FileOffset -> Integer -> Buffer -> IO ()
> > fileGet     :: File -> FileOffset -> Integer -> IO ImmutableBuffer
> Should fileRead return the number of bytes read, in case of=20
> asking for=20
> more bytes than are in the file? With fileGet you can simply=20
> look at the size of the return buffer.

Good point.

> > 	-- | Flushes the buffer to the operating system for an output
> > 	-- buffer, or discards buffered data for an input buffer.
> > 	flush	   	:: s -> IO ()
> Those are two very different things, aren't they? The first=20
> pushes data=20
> along the pipe (rather than discarding it). The second discards data,=20
> equivalent to calling streamGetAvailable and ignoring the result.

It's not quite the same as calling streamGetAvailable.  flush would
discard data that is buffered on the Haskell side, whereas
streamGetAvailable might grab any data that is buffered in the OS.

I'm not sure whether this is useful or not, but it's exactly what hFlush
does currently.
> > 	-- | Flushes the buffered data as far as possible, even to the
> > 	-- physical media if it can.  It returns 'True' if the data
> > 	-- has definitely been flushed as far as it can go: to the=20
> > 	-- disk for a disk file, to the screen for a terminal,=20
> and so on.
> > 	sync		:: s -> IO Bool
> This one seems to be output only. Would it ever be meaningful to call=20
> sync on an input-stream?

You're right.  If flush was moved to OutputStream, then it would make
sense to move sync there too.

> > class InputStream s where
> > class OutputStream s where
> Presumably you wanted Stream superclasses for these?

Not necessarily - there's no need for it, other than to reduce the size
of contexts on types.

> >     streamGet      :: s -> IO Word8
> What does this return after the last byte has been read? What=20
> does this return for an empty file?

Exactly as hGetChar, that is it throws an exception at the end of the

> >  Parameterise InputStream over the element type too, so we can
> >  combine InputStream and TextInputStream?  NO: uses multiparam type
> >  classes.
> Unless of course your stream type is a type constructor:
> class InputStream s where
>   streamGet :: s m e -> m e
>   ...

I can see the advantage in abstracting over the element type (in fact, I
think I'll explore that).

What would be the motivation for abstracting over the monad type?  IMHO,
it has to be done consistently or not at all.  That is, *all* our IO
code should be abstracted over the monad, and I don't think that's a
good idea.