[Haskell-cafe] Observer pattern in haskell FRP

Ertugrul Söylemez es at ertes.de
Tue Nov 27 07:12:34 CET 2012


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

> When writing games in other (imperative) languages, I like to separate
> the game logic from the rendering. For this I use something similar to
> the observer pattern.
>
> [...]
>
> So I am wondering: Is there (or can someone think of) a different
> pattern by which this could be archived? Or asked different: How would
> you do it?

That really depends on the FRP framework you are using.  A framework can
be as simple as to model only the behaviors and events like the original
Fran, in which case often a design pattern such as the observer pattern
is not even available.  One way out of this dilemma is that the main
behavior actually gives enough information to draw the scene.

In more versatile frameworks, which includes basically any modern
framework like Elerea, Netwire and reactive-banana, typically you would
model your entire application including the rendering as part of the
main behavior.  In Netwire you can go as far as having something like
this:

    myApp :: WireM IO a ()

However, I do not recommend this.  As far as possible you should use a
stateless monad, ideally simply Identity or a reader:

    type MyWire = WireM ((->) AppConfig)

    myApp :: MyWire a GameFrame

This is only the first part of the story.  The second part is the
rendering itself.  You certainly want a way to make use of various
OpenGL extensions like vertex buffers, which are inherently stateful.
One sensible way I see is not to output the game's state, but rather a
state delta:

    myApp :: MyWire a GameDelta

That way you can do the imperative stateful plumbing outside of the
application's wire and get the full power of FRP without giving up
efficient rendering.  GameDelta itself would essentially be a type for
game state commands.  In fact it could be a (free) monad:

    myApp :: MyWire a (GameDelta ())

    someDelta :: GameDelta ()
    someDelta = do
        randomPos <- liftA2 (,) getRandom getRandom
        replicateM_ 4 (addCreature randomPos)
        getPlayerPos >>= centerCamOver

Then you could perform that monadic action as part of the rendering
process.


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/haskell-cafe/attachments/20121127/6a82caeb/attachment.pgp>


More information about the Haskell-Cafe mailing list