Haskell 为什么我的程序在播放gloss动画后立即退出?

Haskell 为什么我的程序在播放gloss动画后立即退出?,haskell,gloss,Haskell,Gloss,我正在学习如何使用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

我正在学习如何使用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) 
我在Ubuntu14.04机器上用ghc-make-O2-threaded Main.hs编译了这段代码


当我运行代码时,“Before play”语句被打印出来,然后动画按预期开始。但是,当我关闭动画窗口时,代码立即终止,而不打印“播放后”语句。为什么呢

您可能正在使用GLUT后端(默认)。查看一些for
gloss
(与注释中显示的内容完全相同):

当它退出主循环时,
gloss
将调用
exitBackend
,不管它是什么。对于GLUT,只需调用
System.exitWith
,它自然会终止您的程序。更明智的做法是调用
leaveMainLoop
,但正如代码中的注释所述,
glut
而不是
freeglut
的实现不能很好地使用该函数(为什么?谁知道呢。gloss的作者就是这么说的)


您可能的解决方案是专门使用
freeglut
,并修改
gloss
的源代码以更改
exitBackend
;或者使用GLFW后端,它没有这个问题

可能不相关,但我有一些依赖性问题,导致
play
产生异常(
tmp:user error(未知GLUT条目glutInit)
),因此关闭窗口也可能导致未处理的异常?看起来像是缓冲问题。在退出
hFlush stdout
@mb14之前尝试刷新stout,我仍然遇到同样的问题:-(在Windows 10中测试:关闭时,ghci告诉
freelut():fghInitialize:CreateDC失败,屏幕大小信息可能不正确这很可能是由错误的“-display”参数造成的,然后崩溃,即使在
播放时出现异常处理程序。
instance Backend GLUTState where
        initBackendState           = glutStateInit
        initializeBackend          = initializeGLUT

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

....