Read HTTP header from TCP socket
Perhaps you could wrap bare Sockets in an auxiliary datatype that enabled buffering. Something like:

data BufferedSocket = BufferedSocket [ByteString] Socket


Then you could define your own recv function like

recv :: BufferedSocket -&gt; Int -&gt; IO (BufferedSocket,ByteString)


which looked at the buffer before actually trying to read data from the socket. Note that this version of recv returns a modified copy of the BufferedSocket, because now we carry some state that isn't captured in the mutable Socket reference.

(Perhaps this extra buffer state should be put in a separate mutable reference, an IORef for example. We are already in mutable-land after all.)

We also need a function

putBack :: ByteString -&gt; BufferedSocket -&gt; BufferedSocket


for prepending the data.



Another option could consist in using a streaming library like streaming or streaming-bytestring and build a Stream of ByteStrings out of the Socket. Prepending would consist simply in concatenating a pure Stream that yields the ByteString to the effectful stream that reads from the socket, using &gt;&gt; or *&gt;.

let socketStream' = S.yield someByteStringValue *&gt; socketStream


Note that the old socketStream value should not be reused!

This might have the disadvantage that you lose some control about how many bytes to "physically" read at each step, because typical Streams don't take "feedback" from downstream about the number of bytes to receive next.