haskell – 为什么我的节目在播放光泽动画后立即退出?

我正在学习如何使用Gloss库在
Haskell中制作一些动画.

考虑下面的代码,该代码设置一个圆圈,该圆圈随着时间的推移收缩和扩展其半径.

import Graphics.Gloss
import Graphics.Gloss.Interface.Pure.Game

type Radius = Float
type RealTime   = Float

data World = World Radius RealTime

main :: IO ()
main
 = do   let initWorld = World 100.0 0
        let windowSize = (800,800)
        let windowPosition = (200,200)
        putStrLn "Before play"
        play (InWindow "Wobbling Circle" windowSize windowPosition)
              white 40 initWorld renderWorld handleEvent stepWorld
        putStrLn "After play"

renderWorld :: World -> Picture
renderWorld (World rad rtime ) = Pictures [ Circle rad ]

handleEvent :: Event -> World -> World
handleEvent _ = id

stepWorld ::  Float -> World -> World -- wobbling circle
stepWorld  _ (World _ rtime)  = World (100 * sin rtime) (rtime+0.1) 

我在Ubuntu 14.04机器上用ghc –make -O2 -threaded Main.hs编译了这段代码.

当我运行代码时,打印出“Before play”语句,然后动画按预期开始.但是,当我关闭动画窗口时,代码会立即终止,而不会打印“After Play”语句.这是为什么?

最佳答案 大概你正在使用GLUT后端(默认).看一下
source code的一些光泽(与评论一样):

instance Backend GLUTState where
        initBackendState           = glutStateInit
        initializeBackend          = initializeGLUT

        -- non-freeglut doesn't like this: (\_ -> GLUT.leaveMainLoop)
        exitBackend                = (\_ -> System.exitWith System.ExitSuccess)

....

当它退出主循环时,光泽会调用exitBackend,无论它是什么.对于GLUT,它只是调用System.exitWith,它自然会终止你的程序.更明智的做法是调用leaveMainLoop,但正如代码中的注释所说,除了freeglut之外的过剩实现不能很好地适用于该函数(为什么?谁知道.这就是光泽的作者所声称的).

您可能的解决方案是专门使用freeglut并修改光泽源代码以更改exitBackend;或使用没有此问题的GLFW后端.

点赞