Reactive Banana: State monad or not?
Asked Answered
F

1

7

I have an interface (WX) which is based on Reactive Banana. Now I have different questions about how to really manage the status:

  1. Should I consider the state as the Behaviors that I define in the code?

  2. If the state depends on external "events" too, not only related to the GUI would be better considering IORef?

  3. Or Can I use State Monad? All the examples I saw till now define the network in IO environment. Have any sense stack State Monad and how? With Moment?

Firebox answered 1/9, 2015 at 16:3 Comment(0)
V
4

Should I consider the state as the Behaviors that I define in the code?

For most scenarios you will indeed want to use Behaviors for state. In a GUI application you will often want to update your state in response to interface events. In addition, and crucially, the state must remain existing between occurrences of the events, and State doesn't allow that. More specifically, the standard way to react to an event occurrence doing something other than updating a Behavior is through the reactimate function:

reactimate :: Frameworks t => Event t (IO ()) -> Moment t ()

The action to be performed is of type IO (). While it is possible to use runStateT to run a StateT s IO computation using reactimate, the computation will be self-contained, and you won't have the state it used available to be passed elsewhere. This problem does not arise when using Events to update Behaviors through the reactive-banana FRP interface: the Behaviors remain there until you need to use them again.

If the state depends on external "events" too, not only related to the GUI would be better considering IORef?

Not necessarily. In many cases you can use the tools in Reactive.Banana.Frameworks such as fromAddHandler and newEvent to create Events that are fired when external I/O actions happen. That way you can integrate such actions to your event network. One typical example would be a timer: reactive-banana has no built-in notion of time, but you can introduce a tick event that is fired through an I/O action that happens at regular intervals.

That said, in some cases you might still want to use...

  • ... IORefs (or other sorts of mutable variables, such as MVars), if you have to use a library with an interface that, for whatever reason, restricts your ability to freely react to events using Behaviors and reactimate. A while ago there was a very nice question about such a scenario involving hArduino. The two answers there show different, yet similar in spirit, ways to have an useful event network in unfavourable circumstances.

  • ... StateT if you have some stateful algorithm that is self-contained and whose results won't be used elsewhere in your event network, so that you can run it with runStateT and stick it in a reactimate call. Silly example: an IO () action in reactimate along these lines:

    displayMessageBox . show =<< evalStateT someStateComputation initialState
    
Vines answered 1/9, 2015 at 18:14 Comment(1)
Thank you! I liked the idea about firing newEvent when external I/O action happen. I use similar solutions for CQRS at work but never thought about using it for a GUI app.Firebox

© 2022 - 2024 — McMap. All rights reserved.