2013-05-08 23 views
5

C'è qualcosa che è uguale al contrario di liftIO? Sto usando websockets e voglio essere in grado di ascoltare i messaggi dal server in un thread separato. Ecco quello che sto facendo:Utilizzo di una monade all'interno della monade IO

import Network.WebSockets 
import qualified Data.Text as T 
import Control.Monad.IO.Class 
import Control.Monad 
import Control.Concurrent 
import Control.Applicative 

printMessages :: WebSockets Hybi00() 
printMessages = forever $ do 
    resp <- receiveDataMessage 
    liftIO $ print resp 

run :: WebSockets Hybi00() 
run = do 
    liftIO . forkIO $ printMessages 
    forever $ do 
     line <- liftIO getLine 
     sendTextData . T.pack $ line 

main = connect "0.0.0.0" 8080 "/" run 

Così printMessages ascolta i messaggi dal server e li mantiene stampare. Il problema è che forkIO si aspetta una funzione che restituisce IO(). C'è un modo per me di eseguire printMessages nella monade IO?

+1

[ 'runWithSocket'] (http://hackage.haskell.org/packages/archive/websockets/latest/doc/html/ Network-WebSockets.html # v: runWithSocket) forse? In generale, per passare da un 'MonadIO m' a 'IO', è necessaria una funzione' runXY'. –

risposta

5

Se sto capendo bene, il motivo per cui si desidera ricevere messaggi in un altro thread è perché il thread principale è in attesa dell'input dell'utente da inviare.

Da uno sguardo a the documentation, sembra che avrete un tempo più semplice se si invertono i ruoli dei thread: ricevere nel thread principale e inviare in modo asincrono dall'altro.

Quindi è possibile utilizzare getSink :: Protocol p => WebSockets p (Sink p) per afferrare un lavandino prima si biforcano, che è quindi possibile utilizzare con sendSink :: Sink p -> Message p -> IO() che vive in IO, evitando tutto il problema della miscelazione monadi.

In altre parole, ristrutturare il codice per qualcosa di simile:

sendMessages :: Sink Hybi00 -> IO() 
sendMessages sink = forever $ do 
    line <- getLine 
    let msg = textData . T.pack $ line 
    sendSink sink msg 

run :: WebSockets Hybi00() 
run = do 
    sink <- getSink 
    liftIO . forkIO $ sendMessages sink 
    forever $ do 
     resp <- receiveDataMessage 
     liftIO $ print resp 

main = connect "0.0.0.0" 8080 "/" run 
+1

Grazie! Ho modificato la tua risposta per aggiungere il mio codice di lavoro. –