2012/2/13 Adrien <camarade...@gmail.com>

> On 13/02/2012, Philippe Veber <philippe.ve...@gmail.com> wrote:
> > Dear camlers,
> >
> > I'm looking for advanced examples of GUI programming in functional style.
> > As I'm aware there is no definitive answer on this topic, I'll gladly
> read
> > about pragmatic approaches which may fail to be fully declarative, but do
> > work well in practice. Lately I've been trying to write a little GUI API,
> > replacing all mutable values by React signals (
> > http://erratique.ch/software/react), but it turns out to be more
> difficult
> > than expected, for example with layout management. In order to compute a
> > layout for the widgets, some information has to travel bottom up the
> widget
> > hierarchy, and some goes top down. While there is a well-founded order
> for
> > defining all signals, it's more difficult to group them in their
> respective
> > widget and still avoid mutually recursive definitions. More generally I'd
> > interested in good (and pragmatic !) techniques for GUI programming, with
> > some real life code.
> > Cheers,
> >   Philippe.
>
> Since FRP is quite "new" and not well understood, I'm going to try to
> summarize how I understan it: it makes it possible to use functional code
> for a task that has typically relied on mutability, with all the benefits
> we're used to.
>
With, I think, an additional benefit: making things difficult to write when
we would have done something fishy with mutable references. It's just that
sometimes it's difficult to avoid fishy stufff :o).


>
>
> I've created a lablgtk branch named "adrien/react" to get react signals out
> of gtk properties and react events out of gtk signals (they match quite
> well). Support isn't perfect but enough to test and experiment.
>
> The issue was to write the application itself: it was way too complicated
> and it involved many many react values which had to be somehow kept alive.
> It was also not very useful. The reason was that the very first thing I
> would do with all the events was React.E.select: I would create distinct
> signals only to merge them!
>
> What I've started doing instead is to have one "object" with a
> corresponding
> event: callbacks only send a message to that event and look like "send
> (`Foo
> bar)" and from then I can use match over the message in a different
> location
> in the code, typically in an FRP context.
>
I did that too, and it does seem a good practice: a central bus for
information that is relevant to the whole application. I have a question on
this particular aspect: suppose this bus is updated through the primitive
(broadcast : message -> unit), and that I have a bool event ev that
(indirectly) depends on the bus. Am I allowed to define the following event:

let action = React.E.map (fun b -> if b then broadcast `action ; not b) ev

In other words, am I allowed to call a primitive in a lifted function?


>
>
> (* Warning: this is about work in-progress; it might not always make sense,
> might have some weird things and I might not be able to explain everything
> properly. *)
>
> My current application is a web browser which I want to make much more
> intelligent than the browsers available today.

Just curious: in what way?


> For this reason, I store
> web pages in a data structure which is of course purely functional. I can
> have several layers of data structures containing objects in the same way.
>
> My objects start with a default state and evolve (in a functional way)
> through a fold according to the messages they receive. Each time the state
> changes, two sets of callbacks are triggered: first, to change the UI;
> second, to update the data structure containing the object which is needed
> because of functional updates. I also use that last mechanism to propagate
> messages from the inner objects to the outter ones.
>
> One last characteristic is that I have a UI side besides the functional
> one.
> It contains a handful of things which are needed to work with GTK.I also
> use
> it to propagate messages from the outter objects to the inner ones.
>
> This is work-in-progress and some details could be improved but I think
> that
> the big picture is there. As far as I can tell, the UI and functional sides
> are properly separated, constraints aren't heavy and I seem to be able to
> get the usual qualities of ocaml in GUIs.
>
What module would you recommend reading to get a taste of it?



>
>
> Generally speaking, FRP is not the silver bullet for GUIs. Maybe for
> Haskell
> but definitely not for OCaml. The main reason is probably that most C
> libraries have a specific API which is often very imperative. OCaml
> provides
> references, mutability and objects. If you don't have a big beautiful data
> structure and an actual model for the state of your program, you might want
> to go the easy route and not use FRP but mutability everywhere.
>
Actually I don't use a GUI binding, but directly drawing primitives from
sdl, it looked too difficult for me to use FRP in conjunction with an
existing GUI library, for the very reason you invoke. However I shall have
a close look at the way you made gtk and react coexist. That looks
promising.


>
>
> PS: for layout management, I found that using the ~packing option when
> creating the widgets is usually much better than #add'ing the afterwards.
>

I was hoping to build APIs with this kind of formulation:

let window = panel (hpack [
  picture "picture.bmp" ;
  vpack [
    button "Ok" (fun () -> set_some_event true) ;
    button "Cancel" (fun () -> set_some_event false)
  ]
])

that is avoiding a "create and configure" style. If I can't get that, I'll
probably stick with a traditional, imperative approach.

Thanks for your feedback !
pH.



>
>
> Hope this helps,
> Adrien Nader
>

-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

Reply via email to