反射:创建可重置的延迟事件

Ste*_*gan 5 haskell frp reflex

我在Haskell中使用Reflex,并试图创建一个事件,该事件会触发(出于问题目的)一段指定的时间,比如说2秒。但是,计数器应在原始事件触发时重置,以便如果原始事件相隔1秒触发两次,则第二个事件应仅触发一次:最后一个原始事件后2秒。

我设法实现了这种行为

delayedReset :: MonadWidget t m => Event t () -> m (Event t ())
delayedReset ev = fmap (switch . current) . widgetHold (return never) $ timer <$ ev
  where
    timer = delay 2 =<< getPostBuild
Run Code Online (Sandbox Code Playgroud)

但是使用widgetHold似乎有些矫kill过正。似乎我们只应该真正需要MonadHold约束。有没有更惯用的方式编写此函数?

Ste*_*gan 1

看来我错过了相当明显的:

delayedReset :: MonadWidget t m => Event t () -> m (Event t ())
delayedReset ev = do
    endEv <- delay 2 ev
    countDyn <- foldDyn ($) (0 :: Int) $ leftmost
      [ (+1) <$ ev, subtract 1 <$ endEv ]
    return $ attachPromptlyDynWithMaybe ifZero countDyn endEv
  where
    ifZero 0 a = Just a
    ifZero _ _ = Nothing
Run Code Online (Sandbox Code Playgroud)

限制可以放宽,但这会使它们更加冗长。

但最终我还是选择了第一个解决方案。我认为对性能的影响很小,并且它简化了程序的其他一些方面。