Peter Minten wrote:

I've been trying to get my head around Functional Reactive Programming
by writing a basic explanation of it, following the logic that
explaining something is the best way to understand it.

Am I on the right track with this explanation?

I think so. Your explanation looks fine to me, except for one really subtle but really important issue:

Stepped sounds a lot like stepper and we can create that function by
making a few small adjustments.

    type Time = Int
    stepper :: a -> [(Time, a)] -> (Time -> a)
    stepper d es = \t -> case takeWhile (\(t', _) -> t' <= t) es of
                            [] -> d
                            xs -> snd (last xs)

The correct definition of  stepper  uses  <  instead of  <=

    ... case takeWhile (\(t', _) -> t' < t) es of ...

In other words, at the moment t == t' , the behavior still returns the "old" value, not the "new" value from the event. This important because it allows for recursive definitions, like

    let b = accumB 1 e
        e = (+) <$> b <@ eKey

If you were to use <= here, then the new value of the behavior would depend on itself and the result would be undefined.

(Actually, even if you use the correct definition for stepper, trying to implement Event and Behavior in terms of [(Time,a)] and Time -> a in Haskell would give undefined on this recursive example. That's because the data types still aren't lazy enough, you have to use another model. That's one reason why implementing FRP has traditionally been hard.)


P.S. Sorry about the long mail, the explanation ended up a little longer
than I originally expected. :)

I know it was time to get a blog when my mailing list posts got too long. ;)


Best regards,
Heinrich Apfelmus

--
http://apfelmus.nfshost.com


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to