I Hate IO

Ashley Yakeley ashley@semantic.org
Fri, 10 Aug 2001 18:31:24 -0700

At 2001-08-10 06:26, Simon Marlow wrote:

>There's lots of useful shared functionality between file I/O and socket
>I/O.  For example: buffering/flushing and lazy I/O (getContents) are
>shared for files and sockets in GHC, I wouldn't want to have to provide
>N separate implementations of these things for the various different
>types of streams and files.

I can only tell you what's useful for me as an API user. Since there are 
peculiar little differences between different kinds of sockets, my ideal 
would be every type of socket to have its own API functions, and then 
common patterns brought together with classes.

But at the very least, separate out files from sockets. I'm really not 
sure why files have a "file pointer" stream-based API at all. It seems 
very forced to me, but I guess everyone is so used to it from C/Unix etc. 
that it seems natural. 

>Does doing I/O in anything other than the IO monad make sense?

Probably not. But Sources and Sinks are useful general-purpose patterns.

>Why isn't writeEnd the same as close?

On a TCP connection, one can still receive data after sending an end. My 
"close" is intended to be the last thing done with the connection as an 
object destructor: if called before sending and receiving end, it would 
simply forcibly close the connection.

>Is there anything that is always a Source but not a Sink (or vice

Oh yes, lots of things. Standard input/output/error for instance. One 
might write code that did something like pipe from a Source to a Sink, 
and then one might want a Source constructed from a constant array. Or 
something. Stream-based encoding algorithms such as UTF-8 might make use 
of them:

encodeUTF8:: SourceChar -> SourceWord8


> Why separate these two classes?

I think they are cleanly conceptually separable. I don't see a loss: by 
making TCPSocket an instance of both, the API user still has only one 
object to deal with.

Ashley Yakeley, Seattle WA