我正在使用 Haskell 進行 LOGO 的簡單實作。
對于圖形部分,我使用 Gloss,特別simulateIO是模塊中的函式Graphics.Gloss.Interface.IO.Simulate。
我用它來制作一個視窗并保存我的程式狀態。問題在于更新,它使用了一個 type 函式,ViewPort -> Float -> model -> IO model其中 model 是狀態的型別。我不使用 Viweport 和 Float 引數。我從控制臺讀取一行,決議它并評估它以獲得我在函式結束時回傳的新狀態。
在第一次執行和更新顯示后,它不再更新。當我列印狀態時,我可以看到它正在更新,但顯示沒有。放置一個常量值而不是獲取輸入可以解決問題,但這也不是很有用:)。
這是我的代碼的簡短部分:
runProgram :: Display -> IO ()
runProgram d = simulateIO d white 10 defaultEnv env2Pic step
env2Pic :: Env -> IO Picture
env2Pic e =
...
in return $ pictures piccc
step :: ViewPort -> Float -> Env -> IO Env
step v f e = do
minput <- getLine
case minput of
"" -> step v f e
_ -> case parserComm minput of
Nothing -> print "no parse" >> step v f e
Just cms -> evalPrint e cms
evalPrint 回報 IO Env
有沒有辦法強制重繪?
編輯
看來我的功能運行良好,狀態確實正在修改。我認為問題在于該函式env2Pic不會被simulateIO函式呼叫,只會在開始時呼叫幾次。
我還是想不通為什么。
uj5u.com熱心網友回復:
顯然 step 函式不應該阻塞,所以你不應該像getLine在那個函式中那樣運行阻塞操作。您可以通過getLine在后臺執行緒中運行來解決它。這是一個最小的作業示例:
import Control.Concurrent (forkIO)
import Control.Monad (forever)
import Data.IORef (IORef, atomicWriteIORef, newIORef, readIORef)
import Graphics.Gloss (Display (InWindow), Picture (Text), white)
import Graphics.Gloss.Interface.IO.Simulate
( ViewPort,
simulateIO,
)
runProgram :: IORef String -> Display -> IO ()
runProgram r d = simulateIO d white 10 "" env2Pic (step r)
type Env = String
env2Pic :: Applicative f => Env -> f Picture
env2Pic e = pure (Text e)
step :: IORef String -> ViewPort -> Float -> Env -> IO Env
step r _ _ _ = readIORef r
background :: IORef String -> IO b
background r = forever $ do
x <- getLine
atomicWriteIORef r x
main :: IO ()
main = do
r <- newIORef ""
forkIO $ background r
runProgram r (InWindow "test" (500, 500) (100, 100))
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/387031.html
上一篇:秒差距條件
