0
這是來自我的Traveller項目的子問題。功能性香蕉旅行者 - 輸入處理
我已經放在一起處理輸入的粗魯的代碼。它的工作原理,直到我引入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
獲取輸入。這個想法是,所有玩家將寫入這個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
是正確的選擇?