Reputation: 14660
I am trying to get a simulation running with Gloss in Haskell.
I tried writing a simple script where I want to print "Clicked!" to the terminal every time I click anywhere on the Gloss canvas. The world I pass to the Gloss' play function, is an IO action so I can enable printing to the terminal in response to events.
However, nothing prints to the terminal! :-(
module Main where
import Graphics.Gloss
import Graphics.Gloss.Interface.Pure.Game
import System.IO.Unsafe
data World = World { test :: String
} deriving (Show)
main :: IO ()
main = do
let initialioWorld = return World{test=""} :: IO World
let windowSize = (1800,1800)
let windowPosition = (0,0)
let backgroundColor = orange
let framesPerSecond = 20
play (InWindow "" windowSize windowPosition) backgroundColor framesPerSecond
initialioWorld ( const Blank ) handleEvent (const id)
handleEvent :: Event -> IO World -> IO World
handleEvent event ioworld
| (EventKey (MouseButton LeftButton) Down _ (x,y)) <- event,
World str <- unsafePerformIO ioworld
= do
putStrLn "Clicked!"
return (World str)
| otherwise = ioworld
Now I understand, what Haskell is probably doing is just evaluating that IO action and NOT executing it, and that this has something to do with Haskell's laziness.
So how do I force printing to the terminal in this case?
Upvotes: 2
Views: 686
Reputation: 12749
You are using the pure version of play
. If you want to do IO in the event handler, you must use Graphics.Gloss.Interface.IO.Game.playIO
. With that, the event handler has type
Event -> world -> IO world
Which takes a pure world
, and returns an IO
action that will be executed.
Note that this will also require your drawing and step functions to return IO
actions as well ((return . const Blank)
, and (return . const id)
respectively). Also, you must no longer return
your initial world into IO
.
Upvotes: 3