2013-05-08 13 views
5

Gibt es etwas, das wie das Gegenteil von liftIO ist? Ich benutze WebSockets und möchte Nachrichten vom Server in einem separaten Thread abhören können. Hier ist, was ich tue:Verwenden einer Monade in der IO-Monade

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 

So printMessages für Nachrichten vom Server zuhört und sich aus immer wieder zu drucken. Das Problem ist, forkIO erwartet eine Funktion, die IO() zurückgibt. Gibt es eine Möglichkeit für mich, printMessages in der IO-Monade zu laufen?

+1

[ 'runWithSocket'] (http://hackage.haskell.org/packages/archive/websockets/latest/doc/html/ Network-WebSockets.html # v: runWithSocket) vielleicht? Im Allgemeinen benötigen Sie eine 'runXY'-Funktion, um von einem' MonadIO m' zu 'IO' zu kommen. –

Antwort

5

Wenn ich dieses Recht verstehe, ist der Grund, warum Sie Nachrichten in einem anderen Thread erhalten möchten, weil der Haupt-Thread darauf wartet, dass Benutzereingaben gesendet werden.

Aus einem Blick auf the documentation scheint es, als ob Sie eine einfachere Zeit haben, wenn Sie die Rollen der Threads: im Hauptthread empfangen und asynchron von der anderen senden.

Dann können Sie getSink :: Protocol p => WebSockets p (Sink p) verwenden, um eine Senke zu greifen, bevor gabeln, die Sie dann mit sendSink :: Sink p -> Message p -> IO() verwenden können, die in IO lebt, das ganze Problem der Misch Monaden zu vermeiden.

Mit anderen Worten, restrukturieren Sie Ihren Code so etwas wie dieses:

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

Danke! Ich habe Ihre Antwort geändert, um meinen Arbeitscode hinzuzufügen. –

Verwandte Themen