One option is to use pipes-concurrency

Create a mailbox, and pass to runClient a callback that reads from the Connection and writes to the mailbox

Build a Producer from the other end of the mailbox and consume it in another thread.

Coordinate the threads with something like concurrently from the async package.

On Thursday, October 22, 2015 at 1:42:37 AM UTC+2, Dimitri DeFigueiredo wrote:
Hello All,

I am trying to use both the websockets library and the pipes library. They seem like a natural fit. However, I wanted to use the websockets library to build a pipes 'Producer' and that does not seem possible without some heavy lifting.

The websockets library does not give me a connection I can read from and write to. Instead, I need to supply an IO action (called a clientApp). And execute it using something like:

--runClient :: String       -- ^ Host
--          -> Int          -- ^ Port
--          -> String       -- ^ Path
--          -> ClientApp a  -- ^ Client application -- type ClientApp a = Connection -> IO a
--          -> IO a

main :: IO ()
main = withSocketsDo $ runClient "echo.websocket.org" 80 "/" app

The problem happens when you couple this restriction with the requirement that ClientApps have type 'Connection -> IO a'. Pipes producers are Monad transformer stacks. For example, I would like to build something like:
messageProducer :: Producer' WebsocketMessage IO ()

But this does not run in the IO monad and at the same time I cannot get a 'Connection' object unless I use runClient.

So, it seems I have a catch22 situation. Or have I overlooked something? I'd rather not have to do "un-lifting" on the monad transformer stack.

Has anyone done this before? Any suggestions on how to go about it?


Thanks,


Dimitri