5

有没有与 的相反的东西liftIO?我正在使用 websockets,我希望能够在单独的线程中监听来自服务器的消息。这就是我正在做的事情:

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

所以printMessages监听来自服务器的消息并不断打印出来。问题是,forkIO需要一个返回的函数IO ()。我有什么办法可以printMessages在 IO monad 中运行吗?

4

1 回答 1

5

如果我理解这一点,您想在另一个线程中接收消息的原因是因为主线程将等待用户输入发送。

从查看文档来看,如果您颠倒线程的角色,您似乎会更轻松:在主线程中接收,并从另一个线程异步发送。

然后你可以getSink :: Protocol p => WebSockets p (Sink p)在分叉之前使用它来抓取一个水槽,然后你可以用它来使用sendSink :: Sink p -> Message p -> IO ()IO,避免混合单子的整个问题。

换句话说,将您的代码重组为以下内容:

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
于 2013-05-08T22:39:31.513 回答