I Hate IO
Ashley Yakeley
ashley@semantic.org
Thu, 9 Aug 2001 21:10:01 -0700
At 2001-08-09 03:01, Simon Marlow wrote:
>I considered providing a different API for bidirectional streams, or
>perhaps requiring that bidirectional streams use separate Handles for
>read and write, but came to the conclusion that the user really doesn't
>care whether under the hood a single Handle is using separate buffers
>for read and write or just a single buffer, how much locking is going on
>or whatever. The fact that these things are awkward to implement
>shouldn't show through in the library interface.
>
>It's definitely more convenient from the programmer's point of view to
>be able to use the *same* handle object for both read and write,
>otherwise you have to explain to people why they can have a read/write
>file handle but not a read/write handle for a TCP socket.
Well, how about something like this:
--
type TCPPortNumber = Word16
type IPAddress = Word32
data TCPPort = MkTCPPort IPAddress TCPPortNumber
data TCPSocket = ...
openTCP :: TCPPort -> IO TCPSocket
closeTCP :: TCPSocket -> IO ()
listenTCP :: TCPPortNumber -> (TCPConnection -> IO ()) -> IO ()
-- not sure about listenTCP
getRemoteAddressTCP :: TCPSocket -> IO TCPPort
getLocalAddressTCP :: TCPSocket -> IO TCPPort
receiveTCP :: TCPSocket -> Integer -> Integer -> IO (Maybe [Word8])
-- "receiveTCP socket waittime arraylength"
-- return "Nothing" if received end with no octets pending
-- return "Just array" where array is as many octets up to length as
received by waittime
-- set waittime to 0 to not wait but return only available bytes in
buffer.
receiveWaitForeverTCP :: TCPSocket -> Integer -> IO (Maybe [Word8])
-- Same, with infinite wait-time.
-- only useful if it can be interrupted by another thread
sendDataTCP :: TCPSocket -> [Word8] -> IO ()
sendEndTCP :: TCPSocket -> IO ()
--
OK, this is just off-the-cuff and probably has many flaws, and I offer it
merely for discussion, not as a proposal. It does, however, represent the
kind of basic functionality I'd look for, or abstract, if writing a TCP
application.
If programmers want to abstract away the differences between different
types of network connections, well, this is Haskell so they can always
write classes like this:
--
class (Monad m) => Closable s m | s -> m where
close :: s -> m ()
class (Monad m) => Source s m d | s -> m d where
read :: s -> Integer -> Integer -> m (Maybe [d])
readWaitForever :: s -> Integer -> m (Maybe [d])
class (Monad m) => Sink s m d | s -> m d where
writeData :: s -> [d] -> m ()
writeEnd :: s -> m ()
write s Nothing = writeEnd s
write s (Just d) = writeData s d
-- etc.
--
Ashley Yakeley, Seattle WA