Reactive-banana: updated values ​​fromPoll

I am writing a music player in Haskell with a jet banana. One of the problems I am facing is getting actual values ​​using the fromPoll method. I want the user to be able to optionally select part of the track during playback . My code looks something like this:

makePlayNetworkDescr :: Player a => AddHandler Command -> a -> NetworkDescription t () makePlayNetworkDescr addCmdEvent player = do bPosition <- fromPoll (getPosition player) eCmds <- fromAddHandler addCmdEvent let eSetStart = filterE (isJust) $ bPosition <@ filterE (==SetStart) eCmds eSetEnd = filterE (isJust) $ bPosition <@ filterE (==SetEnd) eCmds eClearRange = filterE (==ClearRange) eCmds bStart = accumB Nothing ((const <$> eSetStart) `union` (const Nothing <$ eClearRange)) bEnd = accumB Nothing ((const <$> eSetEnd) `union` (const Nothing <$ eClearRange)) 

Above, getPosition is a partial function that returns Nothing before playback starts. The problem is that as soon as addCmdEvent is started for the first time, bPosition will still hold the Nothing value. eSetStart / End calculates their values ​​based on this. Only then will bPosition be updated, and this is the value that will be used the next time addCmdEvent is run. And so on, the value will always be “disconnected by one,” so to speak.

There is a related SO question , but in this case there is a trigger event that can be used to compute a new behavior value. Is anything like this possible with the Poll method?

+7
source share
1 answer

For reactive bananas of -0.5 and 0.6, the fromPoll function updates the behavior whenever an external event triggers a network of events. You can access these updates as an event using

 eUpdate <- changes bSomeBehavior 

However, note that the behavior is continuous, time-varying values ​​that do not support the general concept of “update events”. The changes function will try to return a useful approximation, but there are no formal guarantees.

Alternatively, you can modify the external event to include the player’s position as part of addCmdEvent . In your case, this means adding extra data to the SetStart and SetEnd . Then you can use

 eSetStart = filterJust $ matchSetStart <$> eCmds where matchSetStart (SetStart pos) = Just pos matchSetStart _ = Nothing 

Both solutions require you to observe the most recent value as an event, not a behavior. The reason is that the behavior created with stepper will always return to the old value at the time they were updated (they are "behind one"), since this is very useful for recursive definitions.

In any case, the main problem is that the player’s position is updated externally long before addCmdEvent , but the problem is that this is not what the network of events sees. Rather, the network believes that the behavior returned fromPoll is updated at the same time as addCmdEvent . In fact, if you do not have access to the source of external events, which is responsible for updating the player’s position, this is the only thing he might think. (If you have access, you can use the fromChanges function.)

I understand that this fromPoll behavior fromPoll somewhat unsatisfactory for your general use. I have not decided whether I should fix this in my library: there is a compromise between fromPoll returning the last value and the changes function, trying to do everything possible. If the last value is returned, then changes will behave as if it missed one update (when the value was updated externally) and caused excessive (when the network updates the value corresponding to the external one). If you have any opinion on this, let me know.


Note that combining behavior with the applicative operator <*> will combine the most recent values ​​just fine.

+2
source

All Articles