简体   繁体   English

在IO monad中使用monad

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM