Processing mutually recursive graphical GUI widgets with reactive banana widgets

I am looking for a library for writing a GUI on top of GLFW and OpenGL. I do this because I am dissatisfied with the general relationships of the user interface libraries, which I think are too necessary, and I would also like to tightly control the appearance of my user interfaces. I need a declarative approach to defining a user interface. I am experimenting with reactive banana (and temporarily reactive banana-wx) to see if it fits my needs. I have a problem with defining recursive widgets. Here is my simplest test case:

  • Text widget displaying a counter.
  • Button widget that increments the counter.
  • A button widget that is inactive (therefore, it is inactive and does not respond to input at all) when the counter is 0 and otherwise active, and resets the counter to 0.

The first and third widgets have a recursive relationship. The first widget intuitively represents the stepper union events associated with two buttons. However, the reset button is an fmap counter, and then the flow of events depends on the reset button! What to do?

Beyond this question, I am worried about event processing: since I want to handle input input and input focus in my code instead of relying on structure, I see difficulties in correctly dispatching events in a scalable way. Ideally, I would define data , which encapsulates the hierarchical structure of the widget, a way to set event callbacks between elements, and then writes a function that bypasses this data structure to determine device input processing and graphical output. I'm not sure how to take an event stream and break it up as easily as event streams can be combined.

+8
user-interface haskell frp reactive-banana
source share
1 answer

Recursion is allowed if it is a mutual recursion between Behavior and Event . The best part about Behavior is that fetching them during the update will return the old value.

For example, your example can be expressed as follows

 eClick1, eClick2 :: Event t () bCounter :: Behavior t Int bCounter = accumB 0 $ mconcat [eIncrement, eReset] eIncrement = (+1) <$ eClick1 eReset = (const 0) <$ whenE ((> 0) <$> bCounter) eClick2 

See also the question, โ€œCan reactive banana processing cycles be online?โ€


As for your second question, are you looking for a filterE function and its cousins filterApply and whenE ?


As for your overall goal, I think it is rather ambitious. From the little experience that I have gained so far, it seems to me that linking to an existing structure seems completely different than creating a โ€œcleanโ€ structure in FRP. Most likely, there are still undiscovered (but exciting!) Abstractions hiding there. I once started writing an application called BlackBoard , which contains a good abstraction about time-varying drawings.

However, if you care more about results rather than adventures, I would recommend a conservative approach: create an imperative-style GUI toolkit and grab a reactive banana to get the benefits of FRP.

If you just want some kind of GUI, I am currently focusing on the web browser as a GUI. Here are some preliminary experiments with Ji . The main advantage over wxHaskell is that it starts up and runs much easier, and any API development effort will benefit a very wide audience.

+5
source share

All Articles