[Haskell-beginners] Lazy variant of sequence (or other way to approach problem)

Ertugrul Söylemez es at ertes.de
Thu Sep 27 01:45:08 CEST 2012


Nathan Hüsken <nathan.huesken at posteo.de> wrote:

> 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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://www.haskell.org/pipermail/beginners/attachments/20120927/b615eba6/attachment.pgp>


More information about the Beginners mailing list