
Nathan Hüsken
In my (SDL based) haskell program, I do:
events <- liftM ( takeWhile (/= NoEvent)) $ sequence $ repeat pollEvent
The execution of this never returns, I am guessing that is because sequence evaluation never stops.
But if sequence would be lazy (and assuming pollEvent returns NoEvent at some point) this should stop, should it not? Is there a lazy variant of sequence? Or am I missing something here completely?
The sequence function itself cannot be lazy, and there can't be a lazy variant of it. What you want is unsafeLazySequenceIO, which uses unsafeInterleaveIO under the hood, which is IO-specific. As always lazy I/O is probably a bad idea and you should write a coroutine-based combinator for that. The simplest way is the ad-hoc way: pollEvent_ = do ev <- pollEvent case ev of NoEvent -> pollEvent_ _ -> return ev The coroutine-based method would look something like this: import Control.Monad.Trans.Free -- from the 'free' package newtype AppF a = AppF (Event -> a) type App = FreeT AppF IO Since FreeT is effectively just Coroutine from the monad-coroutine package you can use that one instead with the 'Await Event' functor, but the 'free' package provides a lot more useful instances. Your main loop can then suspend to ask for the next event and the surrounding application can provide the event in whatever way it wishes (for example ignoring NoEvent): myLoop = do ev <- await case ev of Quit -> return () _ -> doSomethingWith ev By the way, if your application is non-continuously rendered, which is suggested by your ignoring of NoEvent, you shouldn't use pollEvent at all. Rather you should use waitEvent, which blocks instead of returning NoEvent. That way you don't waste precious CPU cycles. The pollEvent action is meant for applications that are continuously rendered, where you would e.g. perform drawing when you get NoEvent. Hope this helps. Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad.