
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 versa)?
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 etc.
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
participants (1)
-
Ashley Yakeley