Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My Haskell program is too lazy

I have a function like:

type App a = ExceptT AppError (ResourceT IO)

onEvent :: SDL.EventPayload -> App ()
onEvent event = do
  liftIO $ putStrLn "EVE!"
  case event of
    SDL.MouseMotionEvent dat -> do
      liftIO $ putStrLn "HELLO"
    SDL.KeyboardEvent kbe  -> liftIO $ putStrLn "WORLD"
    _ -> return ()

That is a callback being used in my app.

This function seemingly doesn't fire, Because none of the putStrLn's print to console.

But this function - with the slight modification does print everything to console:

onEvent :: SDL.EventPayload -> App ()
onEvent event = do
  liftIO $ putStrLn "EVE!"
  case event of
    SDL.MouseMotionEvent dat -> do
      liftIO $ print dat
    SDL.KeyboardEvent kbe  -> liftIO $ print kbe
    _ -> return ()

Why does the full evaluation of SDL.EventPayload cause the surrounding putStrLn's to work?

How can I make my function callback a bit more reliable?

like image 809
Daniel Hill Avatar asked Jul 26 '16 07:07

Daniel Hill


Video Answer


1 Answers

As Thomas pointed out in the comments, this looks like a buffering problem. The System.IO package describes standard buffering behavior.

You have a couple of options on how to resolve this kind of issue. You can manually set the buffering mode in your program with:

hSetBuffering stdout NoBuffering

at the beginning of your function. This will turn off all buffering (you could also choose LineBuffering) and will print immediately to stdout.

You could also flush the buffer after every print:

SDL.MouseMotionEvent dat -> do
  liftIO $ putStrLn "HELLO"
  hFlush stdout

Or you can try to print directly to the stderr handle which has different default buffering rules:

SDL.MouseMotionEvent dat -> do
  liftIO $ hPutStrLn stderr "HELLO"
like image 95
jkeuhlen Avatar answered Oct 19 '22 08:10

jkeuhlen