
Nathan Hüsken
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.
That sound like a good Idea. But I still have the problem of connection "game logic" objects with "rendering" objects, or am I missing something? Implementing "addCreature" is fine, but when I want a "removeCreature", it has to remove the correct creature from a potentially very large list/set of creatures. How can I efficiently build this connections (which corresponds to a pointer in other languages, I guess)?
That was a simplified example. In the real world it depends on what generates your creatures. If they can be generated all over the code then you need some form of identifier generation. This can be done by the wire's underlying monad: type Identifier = Int type Game = WireM (StateT Identifier ((->) AppConfig)) A creature then may look something like this: creature :: Game World (Creature, GameDelta ()) The wire produces a creating action at the first instant, then switches to the creature's regular wire. The various GameDelta actions form at least a monoid under (>>), and depending on your design even a group: rec (creature1, gd1) <- creature -< w (creature2, gd2) <- creature -< w (creature3, gd3) <- creature -< w w <- delay (World []) -< World [c1, c2, c3] id -< (gd1 >> gd2 >> gd3) That's the basic idea. 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.