
Hey, I have a few question about the usage of netwire: How do I fire events? For example my main wire should take keyboard events as input and output some state (which is than somehow outputed). I see that there is an event type, which has the some type as the identiy wire. I am just not sure how to use it? Or asked differently, how is the "keyDown" event defined, that was talked of in an earlier mail? Thanks! Nathan

I believe I can now at least partly answer my own question: Assuming my input is a list of Key events: data KeyEvent = KeyDown Int | KeyUp Int than the event wire: keyDown code = when (`elem` KeyDown code) :: Event () (->) [KeyEvent] would produce when the key with the given code is pressed down. On 09/28/2012 08:19 PM, Nathan Hüsken wrote:
Hey,
I have a few question about the usage of netwire:
How do I fire events? For example my main wire should take keyboard events as input and output some state (which is than somehow outputed). I see that there is an event type, which has the some type as the identiy wire. I am just not sure how to use it?
Or asked differently, how is the "keyDown" event defined, that was talked of in an earlier mail?
Thanks! Nathan
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Nathan Hüsken
How do I fire events? For example my main wire should take keyboard events as input and output some state (which is than somehow outputed).
The idea is that you either provide the decision of whether to fire an event through the input (direct style) or you use an underlying monad (indirect style). The direct style would have this type: keyDown :: (Monoid e, Reactive cat) => KeySym -> Event e cat SDL.Event The indirect style is nicer to use, but requires an underlying monad: keyDown :: (Monoid e) => KeySym -> Event e (Kleisli MyMonad) a
I see that there is an event type, which has the some type as the identiy wire. I am just not sure how to use it?
The idea is that event wires should act like the identity wire, if an event has happened and inhibit otherwise. That way you can easily put it into a wire composition: time . periodically 1
Or asked differently, how is the "keyDown" event defined, that was talked of in an earlier mail?
In the direct case you can define it as a simple composition: isSym :: KeySym -> SDL.Event -> Bool isSym s (KeyDown s') = s == s' isSym _ _ = False keyDown = require . isSym In the indirect case you can use 'mkFixM' to construct your own wire: keyDown sym = mkFixM $ \_ x -> do ev <- asks currentEvent return $ case ev of KeyDown sym' | sym == sym' -> Right x _ -> Left mempty I 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.

On 09/29/2012 08:56 AM, Ertugrul Söylemez wrote:
Or asked differently, how is the "keyDown" event defined, that was talked of in an earlier mail?
In the direct case you can define it as a simple composition:
isSym :: KeySym -> SDL.Event -> Bool isSym s (KeyDown s') = s == s' isSym _ _ = False
keyDown = require . isSym
While I understand the principals, I am unsure about the practical usage. The input of keyDown is an SDL.Event. But in an application, I would have a list of Events for every invocation of stepWire. So I could define keyDown like this: keyDown s = require . and . map (isSym s) That would give me an event when my desired keypress event is in the list of input events. but if I then want to create a wire passed in this which outputs if a given key is currently pressed, I would attempt something like this: isPressed :: KeySym -> WireP [SDL.Event] Bool isPressed s = hold . (True . (keyDown s) <|> False . (keyUp s)) But if some fast typer releases and presses within one stepWire a certain key, isPressed would produce an incorrect result. Regards, Nathan

Nathan Hüsken
Or asked differently, how is the "keyDown" event defined, that was talked of in an earlier mail?
In the direct case you can define it as a simple composition:
isSym :: KeySym -> SDL.Event -> Bool isSym s (KeyDown s') = s == s' isSym _ _ = False
keyDown = require . isSym
While I understand the principals, I am unsure about the practical usage. The input of keyDown is an SDL.Event. But in an application, I would have a list of Events for every invocation of stepWire. So I could define keyDown like this:
keyDown s = require . and . map (isSym s)
That would give me an event when my desired keypress event is in the list of input events. but if I then want to create a wire passed in this which outputs if a given key is currently pressed, I would attempt something like this:
isPressed :: KeySym -> WireP [SDL.Event] Bool isPressed s = hold . (True . (keyDown s) <|> False . (keyUp s))
But if some fast typer releases and presses within one stepWire a certain key, isPressed would produce an incorrect result.
You can still write isPressed by interpreting it as "has been pressed" instead: isPressed :: KeySym -> WireP [SDL.Event] Bool isPressed sym = True <$ keyUp sym . keyDown sym <|> fix (\again -> False . not (keyDown sym) --> True . not (keyUp sym) --> again) However, I rather recommend against passing multiple SDL events at once. Wires can handle individual events much better and, when properly designed, also faster. 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.

Ertugrul Söylemez
False . not (keyDown sym) --> True . not (keyUp sym) -->
Of course that should be: False <$ not (keyDown sym) --> True <$ not (keyUp sym) --> 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.

On 09/30/2012 05:39 AM, Ertugrul Söylemez wrote:
However, I rather recommend against passing multiple SDL events at once. Wires can handle individual events much better and, when properly designed, also faster.
Ok, so I update my wire on every event I receive. That way I only have one event for every wire update. Now I want my state updates frame based, not time based. I am trying to update the state based on the NoEvent event (the main look takes care that this happens in an constant interval). I have an Event Wire isKeyPressed code :: EventP SDL.Event" which produces when the key is pressed and inhibits when it is not pressed. speed = (((pure (-1.0)) . isKeyPressed leftKeyCode) <|> pure 0.0) + (((pure 1.0) . isKeyPressed rightKeyCode) <|> pure 0.0) So speed is -1 if the left key is pressed, +1 if the right key is pressed and 0 if none or both are pressed. Now I want to integrate this speed (frame based): pos = accum (+) . speed But this does not do the accumulation every frame, but whenever an event happens. So I would need a "require (==NoEvent)" somewhere. But I do not see where I could put it to archive the desired behavior. I am not sure if I am using netwire correctly. Thanks & Regards, Nathan

Nathan Hüsken
Now I want my state updates frame based, not time based. I am trying to update the state based on the NoEvent event (the main look takes care that this happens in an constant interval).
With Netwire you can have your own time frame. For example you can just call stepWire with a constant dt or you can use the counterSession.
I have an Event Wire
isKeyPressed code :: EventP SDL.Event"
which produces when the key is pressed and inhibits when it is not pressed.
speed = (((pure (-1.0)) . isKeyPressed leftKeyCode) <|> pure 0.0) + (((pure 1.0) . isKeyPressed rightKeyCode) <|> pure 0.0)
Let me rewrite this to make it slightly more pleasing to the eye: speed = ((-1) . isKeyPressed leftKeyCode <|> 0) + (1 . isKeyPressed rightKeyCode <|> 0)
So speed is -1 if the left key is pressed, +1 if the right key is pressed and 0 if none or both are pressed.
Now I want to integrate this speed (frame based):
pos = accum (+) . speed
This should be a type error. Rather: pos = accum (+) initialPos . speed
But this does not do the accumulation every frame, but whenever an event happens.
That wire by itself does the accumulation at every frame, so you probably have an inhibiting wire earlier in the chain. 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.

On 10/01/2012 01:58 PM, Ertugrul Söylemez wrote:
Now I want to integrate this speed (frame based):
pos = accum (+) . speed
This should be a type error. Rather:
pos = accum (+) initialPos . speed
Yes of course.
But this does not do the accumulation every frame, but whenever an event happens.
That wire by itself does the accumulation at every frame, so you probably have an inhibiting wire earlier in the chain.
Let me restate my problem. My wire is this: pos = accum (+) 0.0 . speed and all I do is putStrLn the output at every frame. If withing one frame where speed has the value (1) several events are sent over the wire (for example several keyup and keydown events for an unrelated key), then pos gets incremented for one for each of this events. So I have to prevent the accumulation if the event is not NoEvent. Regards, Nathan

Nathan Hüsken
But this does not do the accumulation every frame, but whenever an event happens.
That wire by itself does the accumulation at every frame, so you probably have an inhibiting wire earlier in the chain.
Let me restate my problem. My wire is this:
pos = accum (+) 0.0 . speed
and all I do is putStrLn the output at every frame.
As a side note, see testWire and testWireM in Control.Wire.Session. =)
If withing one frame where speed has the value (1) several events are sent over the wire (for example several keyup and keydown events for an unrelated key), then pos gets incremented for one for each of this events. So I have to prevent the accumulation if the event is not NoEvent.
That's because you're using constant time deltas. Even if your time frame has a constant rate you should still make use of your time deltas. In particular notice that Netwire can deal with time deltas of 0. Then instead of accum you would use integral_. 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.

Hey, I am posting on this old topic because I did not have time in the mean time to concentrate on this in the past weeks and now I resume. On 10/01/2012 02:22 PM, Ertugrul Söylemez wrote:
Nathan Hüsken
wrote: But this does not do the accumulation every frame, but whenever an event happens.
That wire by itself does the accumulation at every frame, so you probably have an inhibiting wire earlier in the chain.
Let me restate my problem. My wire is this:
pos = accum (+) 0.0 . speed
and all I do is putStrLn the output at every frame.
As a side note, see testWire and testWireM in Control.Wire.Session. =)
If withing one frame where speed has the value (1) several events are sent over the wire (for example several keyup and keydown events for an unrelated key), then pos gets incremented for one for each of this events. So I have to prevent the accumulation if the event is not NoEvent.
That's because you're using constant time deltas. Even if your time frame has a constant rate you should still make use of your time deltas. In particular notice that Netwire can deal with time deltas of 0. Then instead of accum you would use integral_.
Yes, ok. But now I want to do something with collision detection and response. So I am trying the stanard FRP Pong example. For the ball I am using ballWire :: PaddleState BallState ballWire = proc ps -> do object_ collDet startState -< (Accelerate (0.0, 0.0), ps) where collDet paddle ball = doCollisionResponseWithPaddleAndWalls paddle ball now I do not want the doCollisionResponseWithPaddleAndWalls to be applied every time an input event is send over the wire but only when the Update event is fired. Now I could add the event type (or the time delta) to the "paddle" argument and test for it collDet (paddle, eventType) ball = if eventType = Update then doCollisionResponseWithPaddleAndWalls paddle ball else ball But this feels like an unnecessary effort ... Thanks! nathan

Nathan Hüsken
If withing one frame where speed has the value (1) several events are sent over the wire (for example several keyup and keydown events for an unrelated key), then pos gets incremented for one for each of this events. So I have to prevent the accumulation if the event is not NoEvent.
That's because you're using constant time deltas. Even if your time frame has a constant rate you should still make use of your time deltas. In particular notice that Netwire can deal with time deltas of 0. Then instead of accum you would use integral_.
Yes, ok. But now I want to do something with collision detection and response. So I am trying the stanard FRP Pong example. For the ball I am using
ballWire :: PaddleState BallState ballWire = proc ps -> do object_ collDet startState -< (Accelerate (0.0, 0.0), ps) where collDet paddle ball = doCollisionResponseWithPaddleAndWalls paddle ball
now I do not want the doCollisionResponseWithPaddleAndWalls to be applied every time an input event is send over the wire but only when the Update event is fired. Now I could add the event type (or the time delta) to the "paddle" argument and test for it
collDet (paddle, eventType) ball = if eventType = Update then doCollisionResponseWithPaddleAndWalls paddle ball else ball
But this feels like an unnecessary effort ...
First of all, Netwire 4 is now released on Hackage. The interface has changed slightly, so you may want to adapt your code. Now to your problem: If you need object_, chances are it's easier to do using mkGen, but in this simple case I doubt that it's necessary. Have a look into the Control.Wire.Trans module tree, where you will find many convenient switching combinators. It should be possible to implement this by using simple integrals and switching. In the next version there will be more switching combinators to make applications like yours easier to write. 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.
participants (2)
-
Ertugrul Söylemez
-
Nathan Hüsken