> As a somewhat separate issue, the logic of half-closed, while it makes
> sense for files, is somewhat bothersome for sockets. If I read the
> docs correctly, once I've grabed the contents lazily, I can no longer
> write to the handle. However, for some things I'd like to do with
> sockets, this is a problem.
>
> Case in point, consider a protocol where I recieve an XML request on a
> socket, and from that generate a response. Sure I can pull the XML
> request in peice by peice using hGetLine (or whatever), such an
> approach seems tedious.
>
> I'd much rather do this:
>
> do contents <- hGetContents socket
> hPutStr socket (processXML contents)
> hClose socket
>
> I can fake this (I think) with unsafeInterleaveIO, but I'd love to
> have such behavior built in.
Yes - I came across this recently while working on GHC's IO library. There
are important distinctions between read/write handles to a file and
read/write handles to some kind of full-duplex data stream such as a socket
or pipe.
A read/write handle to a stream is exactly equivalent to two separate
handles one of which is used for reading and the other writing. In fact you
can do this with GHC's socket library by making two handles from the same
socket (this is a workaround for your problem above). A read/write file on
the other hand contains a shared file pointer, which means it's impossible
to use separate buffers for reading and writing, unless you ensure that only
one is in use at a time. GHC's IO library goes to some trouble to keep this
invariant.
It might make sense to extend this distinction to the API: with a duplex
handle it should be possible to perform write operations on a semi-closed
handle.
Cheers,
Simon