Open fhaust opened 9 years ago
Another question that just came up: Does lazyness apply here? That is: If I start
a SignalGen (Behavior (Foo,Bar))
and only use the Foo
, is Bar
and its dependencies ever evaluated?
Your understanding of Events, Discretes and Behaviors sounds correct, except when you say stepperD
is an endpoint. You can think of a Discrete a
as (Event (), Behavior a)
, where the event fires every time the content of the behavior is possibly changed. When a discrete is updated, all its users are notified, just like when an event fires (i.e. it's pushed).
Regarding laziness, the answer depends on what you mean by evaluated. The library tries to be pure, which means whether an IO action is executed does not depend on whether its result is demanded (unfortunately there is an exception to this rule, namely when you use liftIO in SignalGen). On the other hand, pure function applications are generally left lazy.
This means, for example, the following program prints "foo", "bar", and "f", but not "g".
import Control.Applicative
import FRP.Ordrea
import Debug.Trace
f :: Int -> Int
f x = trace "f" x
g :: Int -> Int
g x = trace "g" x
main = do
sample <- start $ do
foo <- externalB $ do
putStrLn "foo"
return $ f 1
bar <- externalB $ do
putStrLn "bar"
return $ g 1
return $ (,) <$> foo <*> bar
print . fst =<< sample
print . fst =<< sample
print . fst =<< sample
I should really write down all these in Haddock, I'm sorry about the lack of documentation.
I should really write down all these in Haddock, I'm sorry about the lack of documentation.
No sweat ... Actually I am quite happy to have found a FRP implementation that performs well. And if you are familiar with the general FRP concepts the generated haddock documentation is mostly sufficient.
That said there are some functions that are still unclear to me. Scanning the 0.3.0.0 haddocks I find:
changesD
and preservesD
?eventToBehavior
gather all events or just the events since the last sampling call?IO
actions in response to events?Stuff that is clear to me but IMHO would benefit from a little documentation:
stepClockE
is probably an event that fires each time the sample function is called.flattenE
takes an Event [a]
and fires the a
s simultaneous, expandE
does the reverse. But don't worry ... ordrea works to well for me to complain :)
I am in the process of converting a project from reactive-banana to ordrea and am pleased to say that (for my usecase) ordrea is magnitudes faster.
I have just finished reading the push-pull paper by Conal Elliot which I gathered is implemented in ordrea. Still I am unsure about the evaluation semantics used in ordrea. Please correct me if I misunderstood something:
Events
are introduced into the network through thetriggerExternalEvent
functions. These run through the network from the front (push) until they arefilterE
d out and/or hit aDiscrete
. Along the way they trigger evaluation of unevaluatedDiscrete
s andBehavior
s (pull). An example forEvents
would be mouse clicks or keypresses.Discretes
are stateful values that only change in response to incomingEvents
.stepperD
is an endpoint for event streams which will be evaluated when pulled from the "back" of the network. (Is this true? Or areDiscretes
evaluated "to the end" as soon as the first one is triggered?) An example forDiscretes
would be the color of something that is toggled by mouse clicks.Behaviors
are stateful values that may change at any time. Behaviors are only evaluated by need. This will happen when anEvent
is "coming through" or if needed in the evaluation of the network.Behaviors
can only be created throughexternalB
that will sample theIO a
action given to it. An example forBehaviors
would be the current time.Did I get all of this right?