这是我的Traveler项目的一个子问题。
我已经将处理输入的粗略代码放在一起。它有效,直到我将 a 引入TChan
混合中。下面是工作代码,以及如何使用它的示例。然后,我将对其进行更改并解释我这样做的原因。然后,我会谈谈这个问题。
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Monad (forever)
import Control.Concurrent (forkIO)
import Control.Monad.STM (STM,atomically)
import Control.Concurrent.STM.TChan
import Reactive.Banana
import Reactive.Banana.Frameworks
data Planet = Vulcan
| Mars
| Terra
deriving (Eq,Read,Show)
data Command = Move Planet
| Look
| Quit
| Null
deriving Show
makeNetworkDescription :: AddHandler (Maybe Command) -> IO EventNetwork
makeNetworkDescription addCommandEvent = compile $ do
eInput <- fromAddHandler addCommandEvent
let eCommand = filterJust eInput
bCommand = stepper Null eCommand
eCommandChanged <- changes bCommand
reactimate $ (\n -> appendFile "output.txt" ("Command is " ++ show n)) <$>
eCommandChanged
执行以下操作ghci
将证明这是有效的。
(addCommandEvent,fireCommand) <- newAddHandler :: IO (AddHandler (Maybe Command),Maybe Command -> IO ())
networkDescr <- makeNetworkDescription addCommandEvent
actuate networkDescr
return (Just $ Look) >>= fireCommand
所以,现在我已经有了基本的机制,我想开始构建它。这将是一款多人游戏。就输入处理而言,解决此问题的第一步是从TChan
. 想法是,所有玩家都将写入 this TChan
,并且每个命令将按照到达的顺序进行处理。
所以我添加了一个新函数'inputFrame'
inputFrame :: TChan Command -> IO ()
inputFrame commandChannel = do
(addCommandEvent,fireCommand) <- newAddHandler
networkDescr <- makeNetworkDescription addCommandEvent
actuate networkDescr
forkIO $ forever (atomically $ tryReadTChan commandChannel) >>= fireCommand
return ()
这是我尝试使用它的方式,在ghci
.
commandChan <- atomically $ newTChan :: IO (TChan Command)
_ <- atomically $ writeTChan commandChan Look
output.txt
不被写入。commandChan
正在阅读,因为我检查它是否在填充后变为空。我做错了什么很明显吗?如果没有,我该如何解决问题?另外,出于我的预期目的,这是一个TChan
正确的选择吗?