how to create a pipes producer from websockets?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

how to create a pipes producer from websockets?

Dimitri DeFigueiredo
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




_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: how to create a pipes producer from websockets?

John Lenz-2
The yesod-websockets library has a conduit api on top of websockets which I use, so I have conduits processing messages.  Conduit and pipes work similarly, so I suspect the technique from yesod-websockets will work fine for pipes, just look at the yesod-websockets source code:

https://hackage.haskell.org/package/yesod-websockets-0.2.3/docs/Yesod-WebSockets.html

On Wed, Oct 21, 2015 at 6:42 PM, Dimitri DeFigueiredo <[hidden email]> 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




_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe



_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: how to create a pipes producer from websockets?

Daniel Díaz Carrete
In reply to this post by Dimitri DeFigueiredo
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 "<a href="http://echo.websocket.org" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fecho.websocket.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHo_mrF2j-LVLdozPdgP6gpitPAEQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fecho.websocket.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHo_mrF2j-LVLdozPdgP6gpitPAEQ&#39;;return true;">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




_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe