Haskell Gloss,在 animate 函数中从控制台读取不会更新绘图

Haskell Gloss, reading from console within animate function does not update drawing

我正在 haskell.

中简单实现 LOGO

对于图形部分,我使用 Gloss,特别是模块 Graphics.Gloss.Interface.IO.Simulate 中的函数 simulateIO

我用它来制作 window 并保存我的程序状态。问题在于更新,它使用 ViewPort -> Float -> model -> IO model 类型的函数,其中模型是状态的类型。我不使用 Viweport 和 Float 参数。我从控制台读取了一行,对其进行解析并对其求值以获得函数末尾 return 的新状态。

显示第一次执行更新后,不再更新。 当我打印状态时,我可以看到它正在更新,但显示器没有。 放置一个常量值而不是获取输入可以解决问题,但这也不是很有用:)。

这是我的代码的一小部分:

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 returns IO Env

有没有办法强制重绘?

编辑 看来我的功能运行良好,确实在修改状态。我认为问题是函数 env2Pic 没有被 simulateIO 函数调用,一开始只调用了几次。

我还是不明白为什么。

显然 step 函数不应该阻塞,所以你不应该 运行 在该函数中阻塞像 getLine 这样的操作。您可以通过在后台线程中 运行ning 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))