[英]Using a monad inside the IO monad
是否有与liftIO
相反的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 ()
的函数。 有什么办法可以在IO monad中运行printMessages
吗?
如果我理解此权利,那么您想要在另一个线程中接收消息的原因是因为主线程将等待用户输入的发送。
从文档的角度看,如果您反转线程的角色,似乎会更轻松:在主线程中接收,从另一个线程异步发送。
然后可以使用getSink :: Protocol p => WebSockets p (Sink p)
在派生之前抓取一个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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.