Hello fellows,

after a few discussions on IRC and via private mail I feel obligated to
point out that arrows and in particular AFRP do not force you to use an
imperative style in any way.  You can use a style very similar to SHE's
idiom brackets.  I will demonstrate this using the Netwire library.  The
following code has a very imperative feel to it and also looks quite
ugly:

    myWire =
        proc _ -> do
            fps <- avgFpsInt 1000 100 -< ()
            t <- time -< ()
            let x = 3 + t
            y <- integral 0 -< t
            returnA -< printf "%8.2f %8.2f %8.2f" fps x y

Let's improve this code.  The magic lies in identifying behaviors from
classic FRP.  The arrow variables from the above code can be seen as the
behaviors, but that's not very useful for getting rid of the imperative
style.  A better way to look at it is that every wire that ignores its
input (i.e. has a fully polymorphic input type) is a behavior, so let's
find them.

First of all it is impossible to write a proper Num instance for wires.
The underlying problem is the same as for writing a Num instance for
functions.  However, the Wire type forms a vector space, and the next
release of Netwire will include the corresponding instances (see the
vector-space package by Conal Elliot).  With them we can write:

    x = constant 3 ^+^ time

The x wire is our first behavior.  Passing x to a generic wire is
simply regular arrow composition, giving you behaviors as functions of
other behaviors, hence:

    y = integral 0 <<< x

Also fps is just a simple behavior:

    fps = avgFpsInt 1000 100

To get to the final output there are multiple ways.  Perhaps the nicest
way is to exploit the Applicative instance, giving you:

    myWire =
        liftA3 (printf "%8.2f %8.2f %8.2f") fps x y

        where
        fps = avgFpsInt 1000 100
        x   = constant 3 ^+^ time
        y   = integral 0 <<< x

Looks much more declarative, no?  For more complicated compositions or
generic wires use banana brackets or the combinator syntax in arrow
notation.  Examples:

    myWire = proc x ->
        (someWire -< x) ^+^ (otherWire -< 15)

    myWire = proc x ->
        (| f (someWire -< x) (otherWire -< 15) |)

This closely resembles idiom bracket notation, but allows you to be
explicit about inputs, takes care of creating side channels and gives
you the full power of arrows, including ArrowChoice and ArrowLoop.


Greets,
Ertugrul

-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://ertes.de/

Attachment: signature.asc
Description: PGP signature

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

Reply via email to