
On Monday 18 June 2007, Jon Harrop wrote:
On Monday 18 June 2007 05:39:21 Derek Elkins wrote:
Not directed at Michael Richter specifically:
I don't normally say this stuff, but this discussion has drifted onto topics that have nothing to do with Haskell. I personally would like the parts unrelated to Haskell to be carried on off the list.
I don't normally drag threads back on topic, but functional reactive GUIs seem to be pioneered by Haskell programmers. Can anyone explain what this idea is all about?
I'm certainly no expert on FRP, having only read a few papers and never really used such a framework, so take what I say with a grain of salt. However, it seems to me that the main idea behind it is that you should build your GUI (or your robot controller, or whatever) by specifying relationships between various elements, rather than thinking about events and imperative happenings in your program. For instance, say you want to have a button and a label, and have the label display how many times the button's been clicked. In an average imperative toolkit these days, you might do that something like: gui = do b <- newButton l <- newLabel addClickCallback (updateLabel l) b ... where updateLabel l = do x <- getValue l setValue (x+1) l So, you have all your individual GUI components, and you install callbacks for the events you want to know about, and mutate the state of the components accordingly. Now in FRP, you'd instead want to (in some sense) specify the relationship between the label and the button, rather than writing some low-level event-based code that results in such a relationship (I suppose it's a bit like the difference between using triggers and referrential integrity constriants in a relational database). However, when you do this, you want to move away from the view of GUI components as imperative objects with hidden state and such. So you instead think of them, abstractly, as functions Time -> Value, or as streams of Values, or something like that. For the example above, you might have: type Label = Time -> Int type Button = Time -> Maybe () Where a label has a value at any time, and at any time, a button is either being clicked (Just ()) or it isn't (Nothing). Now, your FRP toolkit should provide you with combinators so that you can do soemthing like: label = count button Where count takes a stream of pulses and produces a stream of values corresponding to a running count of the number of pulses. Or, I suppose in the robot world, you might have something that tracks your velocity, and you'd be able to write: position = integral velocity The point being that it's much easier to figure out and write down the relationships you want between various components in your program, and build them compositionally out of various combinators, than it is to write imperative, event-driven code and polling and whatnot. At least, that's the impression I got when I read about it. I could be off. I hope that illuminates things a bit, and isn't too vague. -- Dan