7
votes

Here is the problem: a GUI button has a callback that toggles its state from checked to unchecked.

In imperative programming languages, it is very easy to implement: just modify the Button's state. For example:

void callback(Button btn) {
    btn.setChecked(!btn.getChecked());
}

But in pure functional programming, a callback cannot change the state of an object. The only thing the callback can do is create a new Button object with the new state. For example:

Button callback(Button btn) {
    return new Button(!btn.checked);
}

The button created by the above callback will not be part of the program's GUI, because an external function would have to get the result of the callback and reintegrate the new button value to the GUI.

Furthermore, a button shall not have callbacks with the above type signature, because button callbacks should be generic. I.e. the type signature of a callback would be:

Object callback(Object object);

The only solution I can think of in purely functional code is for callbacks to accept and return the global GUI, e.g.:

GUI callback(GUI gui, Button btn) {
    ...bla bla bla recreate the gui tre ...
}

So how do I do this in purely functional code? how can my purely functional callback change my button's state?

2
Are you working in an existing GUI framework or designing your own?GS - Apologise to Monica
An interesting overview of some functional (pure and impure) techniques: staltz.com/unidirectional-user-interface-architectures.htmlsdgfsdh

2 Answers

2
votes

Probably the most elegant way to design GUIs in a pure functional way is Functional Reactive Programming - see also this SO question and the HaskellWiki page.

If you do things that way then you wouldn't be using callbacks per se, but defining functions that explain how "behaviours" should evolve with time and user input. A button click would be an "event" which would influence the relevant behaviours.

If you want to stick with a more traditional callback model, then I think some degree of imperative behaviour is necessary.

However you can keep the amount of mutability to a minimum by for example having just a single top-level mutable value that represents the entire current state of the program, perhaps somewhat similar to the GUI type you suggested above. The value would be of some complex algebraic datatype that holds everything that can change.

You can also use abstractions that constrain access to that top-level state, e.g. by limiting access to only particular parts of it and only giving access to those abstractions to particular callbacks.

0
votes

Short answer: they (callbacks) can't. Don't try to pull imperative style to the functional world.
Possible solutions are:

  1. You create a new button and re-integrate it into your GUI (as you have mentioned already). Most of functional GUI frameworks will actually go this way.
  2. Your button becomes an infinite lazy stream of states, where a new state is requested upon an event. This is, actually, also an instance of reactive programming (I know you've read wikipedia on that, but sometimes an article on wikipedia is not enough.) In this case, your "callback" is a function to get new state and prepare the "next" one.