[英]Using a monad inside the IO monad
Is there something that is like the opposite of liftIO
? 是否有与
liftIO
相反的liftIO
? I'm using websockets, and I want to be able to listen for messages from the server in a separate thread. 我正在使用websockets,并且希望能够在单独的线程中侦听来自服务器的消息。 Here's what I'm doing:
这是我在做什么:
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
listens for messages from the server and keeps printing them out. 因此,
printMessages
侦听来自服务器的消息,并继续将其打印出来。 The problem is, forkIO
expects a function that returns IO ()
. 问题是,
forkIO
需要一个返回IO ()
的函数。 Is there any way for me to run printMessages
in the IO monad? 有什么办法可以在IO monad中运行
printMessages
吗?
If I'm understanding this right, the reason you want to receive messages in another thread is because the main thread will be waiting for user input to send. 如果我理解此权利,那么您想要在另一个线程中接收消息的原因是因为主线程将等待用户输入的发送。
From a look at the documentation , it seems like you'll have an easier time if you reverse the roles of the threads: receive in the main thread, and send asynchronously from the other. 从文档的角度看,如果您反转线程的角色,似乎会更轻松:在主线程中接收,从另一个线程异步发送。
Then you can use getSink :: Protocol p => WebSockets p (Sink p)
to grab a sink before forking, which you can then use with sendSink :: Sink p -> Message p -> IO ()
which lives in IO
, avoiding the whole problem of mixing monads. 然后可以使用
getSink :: Protocol p => WebSockets p (Sink p)
在派生之前抓取一个getSink :: Protocol p => WebSockets p (Sink p)
器,然后将其与sendSink :: Sink p -> Message p -> IO ()
,它位于IO
,避免了混合单子的整个问题。
In other words, restructure your code to something like this: 换句话说,将您的代码重组为以下形式:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.