On Mon, Feb 28, 2011 at 2:57 PM, wren ng thornton <wren@freegeek.org> wrote:
So then what would become of the string variants? Backwards compatibility
and all... not _everyone_ uses ByteStrings yet.

If you need the String API, specify a dependency on a version of the package that still uses String.

Also, FWIW, the real impetus behind writing these was to deal with lazy
ByteStrings, since that's what one of my dependencies uses[1].

What you really really want, then, is fdWriteAll, which repeatedly uses writev to write all of a list of strict (or a single lazy) bytestring to an fd, no? That's why I added sendAll to network-bytestring, because it's absolutely the common case that you want to write everything you can to a file descriptor, and not have to worry about short writes.
 
It seems
like a common enough situation that it should be handled directly. Forcing
people to call (BS.concat . BL.toChunks) first muddies up the code and
introduces additional copying, whereas making people use (mapM_ fdWrite .
BL.toChunks) is still rather messy and it's buggy in the face of partial
writes.

Well, wait. That paragraph portion seems to confuse things. At the very least, it confuses me, because I surely didn't suggest using concat, as that would be silly. I want to see four entry points for writing:

fdWrite :: Strict.ByteString -> IO Int
fdWriteAll :: Strict.ByteString -> IO ()
fdWritev :: [Strict.ByteString] -> IO Int -- turn the list into an iovec, then call writev
fdWritevAll :: [Strict.ByteString] -> IO ()

People would normally use the 'All' variants, but there are times when you really do want to know if you've performed a short write so that you can handle it yourself.