Skip to content

Latest commit

 

History

History
77 lines (58 loc) · 2.88 KB

05-producers.md

File metadata and controls

77 lines (58 loc) · 2.88 KB

Producers

Related to Tasks, Monomer also provides the concept of Producers. Both serve the purpose of being able to run arbitrary IO code, but while Tasks only return a single result, Producers allow sending an unlimited number of events back to the application. This makes them useful for consuming streams of data, as needed to implement a chat application or a stock ticker.

Creating a producer

In the example, probably the simplest stream of data is consumed: the current time.

The producer is created when the application starts by responding with a Producer to the init event. Producer takes a function slightly different to what is provided to Task:

  • It receives a function as an argument. This function is provided by the library and is used for sending messages back to the application.
  • It has () return type, meaning the only way of sending information to the application is through the function provided as argument.
handleEvent wenv node model evt = case evt of
  AppInit -> [Producer timeOfDayProducer]
  AppSetTime time -> [Model $ model & currentTime .~ time]

timeOfDayProducer :: (AppEvent -> IO ()) -> IO ()
timeOfDayProducer sendMsg = do
  time <- getLocalTimeOfDay
  sendMsg (AppSetTime time)
  threadDelay $ 1000 * 1000
  timeOfDayProducer sendMsg

In the example the producer requests the current time, sends a message using the provided function, waits for one second (threadDelay uses nanoseconds) and, finally, calls itself recursively to repeat the process for as long as the application runs.

Once the event is received, the application updates its model as usual.

You can check the Ticker example to see a websocket based Producer.

New widgets

Animation

In the example, every ten seconds the time label will flash. This effect is generated by the animFadeIn animation, which is restarted with that frequency. The way to start/restart an animation is by sending it a message. This requires the widget key of the target plus the expected message.

fadeInMsg time
  | truncate (todSec time) `mod` 10 /= 0 = []
  | otherwise = [Message "fadeTimeLabel" AnimationStart]

In the case of animFadeIn/animFadeOut (there is also animSlideIn/animSlideOut), the possible messages are:

  • AnimationStart: Causes the animation to start from the beginning.
  • AnimationStop: Causes the animation to stop if currently running.

Messages are not only used for animation purposes, as other widgets can receive messages to perform custom operations. For example, scroll can receive ScrollTo Rect, to make sure a specific part of its content is visible. Each widget that supports messages has them documented in their Haddock page.


Next: Composite