On Sun, Mar 3, 2013 at 10:24 PM, Joey Adams <joeyadams3.14159@gmail.com> wrote:
...
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)
    ...

While trying to implement this, I found a more elegant interface for resuming the ResumableConduit:

    -- | Fuse a 'ResumableConduit' to a 'Sink'.  When the 'Sink' returns,
    -- it returns the 'ResumableConduit' so the caller can reuse it.
    (=$++) :: Monad m
           => ResumableConduit i m o
           -> Sink o m r
           -> Sink i m (ResumableConduit i m o, r)

This takes advantage of Sink's return value to forward the ResumableConduit.  I don't think a ($=++) can be implemented.

Advantages:

 * (=$++) is easier to implement than 'runResumableConduit' since it only has to fuse two pipes together instead of three.

 * Pretty syntax: (resumable', a) <- source $$ resumable =$++ sink