[Haskell-cafe] Is this a correct explanation of FRP?

Ertugrul Söylemez es at ertes.de
Fri Mar 30 02:30:14 CEST 2012

Peter Minten <peter.minten at orange.nl> 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?

You are explaining a particular instance of FRP.  Functional reactive
programming is not a single concept, but a whole family of them.
Traditional FRP as implemented by reactive-banana (and older libraries
like Elerea, Fran and Reactive) is based on behaviors and events.  It
uses the notion of a time-dependent value in a direct fashion.
Conceptionally traditional FRP is this:

    Behavior a = Time -> a
    Event a    = [(Time, a)]

    -- The current time at even seconds and half the current time at odd
    -- seconds:

    alterTime = fullTime
    fullTime = switch (after 1) currentTime halfTime
    halfTime = switch (after 1) (fmap (/ 2) currentTime) fullTime

There is a second instance of FRP though called AFRP.  The A stands for
"arrowized", but in modern times I prefer to think of it as
"applicative".  The underlying control structure is now a category and
the concept of a time-varying value is changed to a time-varying
function (called signal function (SF)), which is just an automaton and
there is an arrow for it.  This simplifies implementation, makes code
more flexible and performance more predictable.  The libraries Animas
and Yampa implement this concept (Animas is a fork of Yampa).

    SF a b    = a -> (b, SF a b)
    Event a b = SF a (Maybe b)

    alterTime = fullTime
    fullTime = switch (after 1) currentTime halfTime
    halfTime = switch (after 1) ((/ 2) ^<< currentTime) fullTime

Now both the predefined event function 'after' and the predefined signal
'currentTime' are signal functions.  It also allows to implement some
analysis tools easily:

    -- Emit an event whenever the given signal function's output
    -- changes:

    changesOf :: (Eq b) => SF a b -> SF a (Maybe b)

Finally there is an extension of AFRP of which I'm the proud
inventor. =) By generalizing the automaton arrow to allow what I call
signal inhibition you get to the wire arrow.  This adds another layer of
flexibility, unifies the notions of time-varying functions and events
and completely removes the need for switching.  Events can now be
handled implicitly.  The library Netwire implements this concept.

    Wire a b  = a -> (Maybe b, Wire a b)
    Event     = Wire

    changesOf :: (Eq b) => Wire a b -> Wire a b

    alterTime = fullTime <|> halfTime
    fullTime = when (even . floor) . time
    halfTime = fmap (/ 2) time


nightmare = unsafePerformIO (getWrongWife >>= sex)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20120330/9de8e4fb/attachment.pgp>

More information about the Haskell-Cafe mailing list