Thanks for the response. I spent some time thinking about leftovers and understand the Category issue now. Thanks for clearing that up.
While trying to work conduits into a program I'm working on, I find myself wanting something more powerful: a resumable Conduit.
For example, consider receiving a stream of messages over a network:
data Message = Data ByteString | CompressedData ByteString | RestartCompressor
When CompressedData is received, feed the bytes to a decompressor conduit. When RestartCompressor is received, close the first decompressor conduit and fire up a new one.
Supporting restarts needs more than just Conduit i m o -> Conduit (Either x i) m (Either x o). It involves opening and closing a conduit within another conduit's operations.
Here's a possible API for a resumable Conduit:
newtype ResumableConduit i m o = -- hidden --
newResumableConduit :: Monad m => Conduit i m o -> ResumableConduit i m o
-- | Feed the 'Source' through the conduit, and send any output from the
-- conduit to the 'Sink'. When the 'Sink' returns, close the 'Source', but
-- leave the 'ResumableConduit' open so more data can be passed through it.
runResumableConduit
:: Monad m
=> ResumableConduit i m o
-> Source m i
-> Sink o m r
-> m (ResumableConduit i m o, r)
-- | Tell the conduit there is no more input available, and send the remaining
-- output (if any) to the 'Sink'.
closeResumableConduit
:: Monad m
=> ResumableConduit i m o
-> Sink o m r
-> m r
Does anyone want to comment on this interface?
Perhaps conduit could have a module called "Data.Conduit.Resumable" that contains ResumableSource, ResumableConduit, and ResumableSink. The conduit-resumablesink package by Andrew Miller [1] implements ResumableSink; it just needs to be updated for conduit 1.0.
[1]:
http://hackage.haskell.org/package/conduit-resumablesink