From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail1-relais-roc.national.inria.fr (mail1-relais-roc.national.inria.fr [192.134.164.82]) by walapai.inria.fr (8.13.6/8.13.6) with ESMTP id q1EA3mrr015575 for ; Tue, 14 Feb 2012 11:03:48 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AmcBACwxOk/RVdQ2kGdsb2JhbABDn1yQSAgiAQEBAQkJDQcUBCOBcgEBAQMBEgITGQEbHQEDAQsGBQsNLiEBAREBBQEcBhMZCYdaCZwmCotxgnCFKT+IcwIFC4g5gxIBAgECAwUBBAUFAQIBBAEDAw4BAgEEP4NoHzYDAQwDBQELgy8ElTKLEIMVPYQD X-IronPort-AV: E=Sophos;i="4.73,416,1325458800"; d="scan'208";a="144149793" Received: from mail-vw0-f54.google.com ([209.85.212.54]) by mail1-smtp-roc.national.inria.fr with ESMTP/TLS/RC4-SHA; 14 Feb 2012 11:03:14 +0100 Received: by vbbfa15 with SMTP id fa15so7129167vbb.27 for ; Tue, 14 Feb 2012 02:03:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=FVgjm7DNHbH1sbV75SPgPW2VtpBpbCzRcxaDM29d408=; b=Rsz9QGv58BgYmMTQRRvrhk/h6+BIOYOzqWaLtar5WHdhVHY5LPBxkcjhkAwEAtV7An hcY8/GIPyQtnX510m3liTwhTcKg0p9Y4JGTLB4Jt5yduesE0iCnp3T7PSNWYKILyBjmN JLVUPrJ+uSpfp6yiyJlC9t1BJyj9b10/QU4nU= Received: by 10.220.238.200 with SMTP id kt8mr3783086vcb.23.1329213793196; Tue, 14 Feb 2012 02:03:13 -0800 (PST) MIME-Version: 1.0 Received: by 10.52.90.140 with HTTP; Tue, 14 Feb 2012 02:02:53 -0800 (PST) In-Reply-To: References: From: Philippe Veber Date: Tue, 14 Feb 2012 11:02:53 +0100 Message-ID: To: Adrien Cc: caml users Content-Type: multipart/alternative; boundary=14dae9cfccb8f959df04b8e9b327 X-Validation-by: philippe.veber@gmail.com Subject: Re: [Caml-list] Functional GUI programming: looking for good practices --14dae9cfccb8f959df04b8e9b327 Content-Type: text/plain; charset=ISO-8859-1 2012/2/13 Adrien > On 13/02/2012, Philippe Veber 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 > --14dae9cfccb8f959df04b8e9b327 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable

2012/2/13 Adrien <<= a href=3D"mailto:camaradetux@gmail.com" target=3D"_blank">camaradetux@gmail= .com>
On 13/02/2012, Philippe Veber <philippe.veber@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 G= UI 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 w= idget
> 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 r= espective
> widget and still avoid mutually recursive definitions. More generally = I'd
> interested in good (and pragmatic !) techniques for GUI programming, w= ith
> some real life code.
> Cheers,
> =A0 Philippe.

Since FRP is quite "new" and not well understood, I&#= 39;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 benefi= t: making things difficult to write when we would have done something fishy= with mutable references. It's just that sometimes it's difficult t= o avoid fishy stufff :o).
=A0


I've created a lablgtk branch named "adrien/react" to get rea= ct 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.<= br> 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 lo= cation
in the code, typically in an FRP context.
I did that t= oo, 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 as= pect: suppose this bus is updated through the primitive (broadcast : messag= e -> 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 =3D React.E.map (fun b -> if b then broadcast `action ; n= ot b) ev

In other words, am I allowed to call a primitive in a lifte= d function?
=A0


(* 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<= br> properly. *)

My current application is a web browser which I want to make much more
intelligent than the browsers available today.
Just curio= us: in what way?
=A0
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.<= br>
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<= br> changes, two sets of callbacks are triggered: first, to change the UI;
second, to update the data structure containing the object which is needed<= br> because of functional updates. I also use that last mechanism to propagate<= br> 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 us= e
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 tha= t
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?

=A0


Generally speaking, FRP is not the silver bullet for GUIs. Maybe for Haskel= l
but definitely not for OCaml. The main reason is probably that most C
libraries have a specific API which is often very imperative. OCaml provide= s
references, mutability and objects. If you don't have a big beautiful d= ata
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 prim= itives from sdl, it looked too difficult for me to use FRP in conjunction w= ith an existing GUI library, for the very reason you invoke. However I shal= l have a close look at the way you made gtk and react coexist. That looks p= romising.
=A0


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

I was hoping to build APIs with this kind of fo= rmulation:

let window =3D panel (hpack [
=A0 picture "pictur= e.bmp" ;
=A0 vpack [
=A0=A0=A0 button "Ok" (fun () -> set_some_even= t true) ;
=A0=A0=A0 button "Cancel" (fun () -> set_some_eve= nt false)
=A0 ]
])

that is avoiding a "create and config= ure" style. If I can't get that, I'll probably stick with a tr= aditional, imperative approach.
=A0
Thanks for your feedback !
pH.

=A0


Hope this helps,
Adrien Nader

--14dae9cfccb8f959df04b8e9b327--