Creating a Behavior for a continuously measurable phenomenon

Viewed 261

I would like to create a Behavior t a from an IO a, with the intended semantics that the IO action would be run every time the behavior is sampled:

{- language FlexibleContexts #-}
import Reflex.Dom
import Control.Monad.Trans

onDemand :: (MonadWidget t m, MonadIO (PullM t)) => IO a -> m (Behavior t a)

I hoped I could do this by just executing the measurement in a pull:

onDemand measure = return $ pull (liftIO measure)

However, the resulting Behavior never changes after an initial measurement.

The workaround I could come up with was to create a dummy Behavior that changes "frequently enough" and then create a fake dependency on that:

import Data.Time.Clock as Time

hold_ :: (MonadHold t m, Reflex t) => Event t a -> m (Behavior t ())
hold_ = hold () . (() <$)

onDemand :: (MonadWidget t m, MonadIO (PullM t)) => IO a -> m (Behavior t a)
onDemand measure = do
    now <- liftIO Time.getCurrentTime
    tick <- hold_ =<< tickLossy (1/1200) now
    return $ pull $ do
        _ <- sample tick
        liftIO measure

This then works as expected; but since Behaviors can only be sampled on demand anyway, this shouldn't be necessary.

What is the correct way to create a Behavior for a continuous, observable-at-any-time phenomenon?

2 Answers
Related