<div>Move to haskell-cafe you two.</div><div><br></div><div>(j/k -- I think the discussion is great here. If you also cc'ed -cafe, your points would get higher visibility.)</div><div><br></div><br clear="all">-- Kim-Ee<br>
<br><br><div class="gmail_quote">On Fri, Sep 21, 2012 at 8:53 AM, Ertugrul Söylemez <span dir="ltr"><<a href="mailto:es@ertes.de" target="_blank">es@ertes.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">Heinrich Apfelmus <<a href="mailto:apfelmus@quantentunnel.de">apfelmus@quantentunnel.de</a>> wrote:<br>
<br>
> > Wire is also an Alternative, which allows concise and efficient<br>
> > switching with very little cruft. The following wire renders "yes"<br>
> > when the "keyDown Space" event happens and "no" otherwise:<br>
> ><br>
> > pure "yes" . keyDown Space <|> pure "no"<br>
> ><br>
> > Or with the OverloadedStrings extension:<br>
> ><br>
> > "yes" . keyDown Space <|> "no"<br>
> ><br>
> > All classic (non-wire) FRP implementations need switching or another<br>
> > ad-hoc combinator for this. If you happen to need switching it's<br>
> > also a lot simpler using wires:<br>
> ><br>
> > "please press space" . notE (keyDown Space) --> "thanks"<br>
> ><br>
> > This one waits for the Space key and then outputs "thanks" forever.<br>
> > So far Netwire has the fastest and most elegant way of dealing with<br>
> > events compared to all other libraries I have tried.<br>
><br>
> These examples look neat!<br>
><br>
> I'm a bit confused about the model you are using, though. If I<br>
> understand that correctly, you don't distinguish between events and<br>
> behaviors; rather, you are working with data streams in discrete time<br>
> steps. Still, I don't quite understand.<br>
<br>
</div>First let me try to put reactive-banana's model into a data type of my<br>
own, which you might call TimedZipStream. The name Behavior is easier,<br>
so let me pick that one instead (Time is the type for time deltas):<br>
<br>
newtype Behavior a =<br>
Behavior {<br>
stepBehavior :: Time -> Network (a, Behavior a)<br>
}<br>
<br>
This is not anywhere near how reactive-banana represents its behaviors,<br>
but just a simplified and less powerful model. The argument is the time<br>
delta to the last instant. Communication happens through the Network<br>
monad and is opaque to the user. The type is an applicative functor<br>
that represents values that can behave differently at each instant.<br>
<br>
My model is similar to Yampas model, where instead of time-varying<br>
values you have time-varying functions, so-called signal functions:<br>
<div class="im"><br>
newtype SF a b =<br>
</div> SF {<br>
stepSF :: Time -> a -> (b, SF a b)<br>
}<br>
<br>
This is a function from an 'a' to a 'b' that mutates over time. There<br>
is a counterpart for classic behaviors, which is when the input type is<br>
fully polymorphic:<br>
<br>
time :: SF a Time<br>
<br>
SF forms a family of applicative functors, but now there is a direct<br>
path from one signal function to the next, because SF is itself a<br>
category. No graph, no monad, just plain categorical composition.<br>
Unfortunately to this day Yampa does not provide an Applicative<br>
instance, so you have to use the Arrow interface, which is usually very<br>
ugly.<br>
<br>
The weak spot of both models is events. They need to be handled using<br>
switchers and other combinators. Causality, simultaneity and choice all<br>
need to be encoded explicitly. Event modifiers work outside of the<br>
behavior level.<br>
<br>
What makes Netwire different? Wire categories are encoded by the<br>
following (simplified) type:<br>
<div class="im"><br>
newtype Wire e a b =<br>
</div> Wire {<br>
stepWire :: Time -> a -> (Either e b, Wire e a b)<br>
}<br>
<br>
Wires can choose not to output anything, but instead inhibit with a<br>
value of type 'e'. Where i is an inhibiting wire the following<br>
identities hold:<br>
<br>
x . i = i<br>
i . x = i<br>
<br>
Furthermore now when 'e' is a Monoid Wire is a family of Alternative<br>
functors with the following identities, where x and y produce and i, j<br>
and ij' and inhibit:<br>
<br>
x <|> y = x<br>
i <|> y = y<br>
<br>
i <|> j = ij'<br>
<br>
The ij' wire also inhibits, but mappend-combines the inhibition values.<br>
The empty wire always inhibits with mempty. The monoid is necessary for<br>
the Category, Applicative and Alternative laws to hold.<br>
<div class="im"><br>
<br>
> What is<br>
><br>
> pure "yes" . keyDown Space <|> pure "no"<br>
><br>
> supposed to mean? If it's a function Time -> String , how long does it<br>
> have the "yes" value? 439.7 milliseconds? If it's an event, how often<br>
> does the "no" event fire?<br>
<br>
</div>An event wire is a wire that acts like the identity wire when it<br>
produces, but may choose to inhibit instead:<br>
<div class="im"><br>
pure "yes" . keyDown Space<br>
<br>
</div>The 'keyDown Space' wire acts like the identity wire when the space key<br>
is pressed, otherwise it inhibits. As a consequence of the above laws<br>
the composition also inhibits. This is where (<|>) comes in:<br>
<div class="im"><br>
pure "yes" . keyDown Space <|> pure "no"<br>
<br>
</div>When the left wire inhibits, the right wire takes over. By definition a<br>
'pure' wire never inhibits. Notice that in this example I'm assuming<br>
that 'keyDown' is a 'continuous event'. That's where behaviors are<br>
mixed with events. An event can actually have a duration.<br>
<br>
If 'keyDown' would be instantaneous without a duration you could use the<br>
'holdFor' combinator:<br>
<br>
pure "yes" . holdFor 1 (keyDown Space) <|> pure "no"<br>
<br>
This would also work for a continuous 'keyDown' event wire. Then if you<br>
press the space key for one second, "yes" is displayed for two seconds.<br>
<div class="im"><br>
<br>
> Concerning the other example, I don't understand what the expression<br>
><br>
> "please press space" . notE (keyDown Space)<br>
><br>
> means. If it's a function, what value does it have when the key was<br>
> pressed? If it's an event, how often does it "fire" the string value?<br>
<br>
</div>In this case it doesn't really matter if 'keyDown Space' has a duration<br>
or not. As soon as it produces once, the switch happens and the next<br>
wire takes over. There is another name for the (-->) combinator called<br>
'andThen'.<br>
<br>
x --> y<br>
<br>
As soon as x inhibits, this combination switches to y.<br>
<br>
Side note: Unlike classic FRP a wire category is not time-bound. In<br>
fact in the current official release of Netwire (3.1.0) time is actually<br>
an extension. In Netwire time is back as a primitive, because it makes<br>
time-related wires (the analog to behaviors) much easier to write. I<br>
have retained the flexibility that your wire can have a time frame<br>
different from real time, though.<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
Greets,<br>
Ertugrul<br>
<br>
--<br>
Not to be or to be and (not to be or to be and (not to be or to be and<br>
(not to be or to be and ... that is the list monad.<br>
</div></div><br>_______________________________________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/beginners" target="_blank">http://www.haskell.org/mailman/listinfo/beginners</a><br>
<br></blockquote></div><br>