Creating a Behavior for a continuously measurable phenomenon

前端 未结 2 1521
天命终不由人
天命终不由人 2021-02-20 05:05

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 sample

2条回答
  •  盖世英雄少女心
    2021-02-20 05:56

    I've been experimenting with this for a while and found a workaround. It seems to work with the latest version of reflex to date. The trick is to forcefully invalidate the cached value every time you evaluate a given IO action.

    import qualified Reflex.Spider.Internal as Spider
    
    onDemand :: IO a -> Behavior t a
    onDemand ma = SpiderBehavior . Spider.Behavior
                . Spider.BehaviorM . ReaderT $ computeF
      where
        computeF (Nothing, _) = unsafeInterleaveIO ma
        computeF (Just (invW,_), _) = unsafeInterleaveIO $ do
            toReconnect <- newIORef []
            _ <- Spider.invalidate toReconnect [invW]
            ma
    

    It is important to use unsafeInterleaveIO to run the invalidator as late as possible, so that it invalidates an existing thing.

    There is another problem with this code: I ignore toReconnect reference and the result of invalidate function. In current version of reflex, the latter is always empty, so it should not cause any problems. But I am not sure about toReconnect: from the code, it seems that if it has some subscribed switches, they might break if not treated properly. Though I am not sure if this kind of behavior can have switches subscribed or not.

    UPDATE for those who really want to implement this: The code above can deadlock in some complicated setups. My solutions was to perform invalidation slightly after the computation itself in a separate thread. Here is the complete code snippet. The solution by the link seems to work correctly (using it for almost a year now in production).

提交回复
热议问题