Reputation: 57
I'm working in a simple implementation of LOGO in haskell.
For the graphic part I'm using Gloss, in particular the function simulateIO
from the module Graphics.Gloss.Interface.IO.Simulate
.
I use it to make a window and save the state of my program. The problem is with the updates, it uses a function of type ViewPort -> Float -> model -> IO model
where model is the type of the state. I don't use the Viweport and Float arguments. I read a line from console, parse it and evaluate it to get a new state that I return at the end of the function.
After the first execution and update of the display, it doesn't update anymore. When I print the state I can see it is updating, but the display does not. Putting a constant value instead of getting the input fixes the problem, but that is nor very useful :).
Here is a brief part of my code:
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
Is there a way to force the redrawing?
EDIT
It seems that my function is working well and the state is indeed being modified. I think the problem is that the function env2Pic
doesn't get called by the simulateIO
function, only a few times at the start.
I still can't figure out why.
Upvotes: 3
Views: 295
Reputation: 10645
Apparently the step function is not supposed to block, so you should not run blocking operations like getLine
in that function. You can work around it by running getLine
in a background thread. Here is a minimal working example of that:
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))
Upvotes: 2