haskellreactive-banana

Reactive Banana: State monad or not?


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?


Solution

  • 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...