Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
From: Adrien <camaradetux@gmail.com>
To: Philippe Veber <philippe.veber@gmail.com>
Cc: caml users <caml-list@inria.fr>
Subject: Re: [Caml-list] Functional GUI programming: looking for good practices
Date: Mon, 13 Feb 2012 16:27:54 +0100	[thread overview]
Message-ID: <CAP5QFJ=-K_gFU6ijnVW3xrUs2HDcQJ8raKQZZhafEMsyAB1WVw@mail.gmail.com> (raw)
In-Reply-To: <CAOOOohRwOdr4xtt1XH2y1-9_XQ10Fq_1ocGD8i8pUSVqkHvQng@mail.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 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.


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.


(* 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. 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.


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.


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


Hope this helps,
Adrien Nader

  reply	other threads:[~2012-02-13 15:27 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-13 11:01 Philippe Veber
2012-02-13 15:27 ` Adrien [this message]
2012-02-14 10:02   ` Philippe Veber
2012-02-14 10:21     ` Daniel Bünzli
2012-02-14 10:39       ` Philippe Veber
2012-02-14 11:52         ` Adrien
2012-02-14 13:00           ` Daniel Bünzli
2012-02-14 13:29     ` Adrien
2012-02-13 18:13 ` Raoul Duke
2012-02-14  0:36   ` Anthony Tavener
2012-02-14 10:17     ` Philippe Veber
2012-02-14 18:02       ` Anthony Tavener
2012-02-15  4:47         ` Anthony Tavener
2012-02-22 11:57           ` Philippe Veber
2012-02-28 10:10             ` Adrien

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAP5QFJ=-K_gFU6ijnVW3xrUs2HDcQJ8raKQZZhafEMsyAB1WVw@mail.gmail.com' \
    --to=camaradetux@gmail.com \
    --cc=caml-list@inria.fr \
    --cc=philippe.veber@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox