即使值没有改变,我是否还要担心动态触发?

Do I have to worry about a Dynamic firing even when the value does not change?

使用 reflex-dom 我发现自己编写了以下代码:

dynShowNumbers <- holdDyn False $ catMaybes $ updated dynMaybeShowNumbers

其中 dynMaybeShowNumbers :: Dynamic t (Maybe Bool) 触发,只要按下或释放一个键,但它只有一个不等于 Nothing 的值,当两个特定键之一改变状态时(即按下或未按下) ).当释放两个键之一时,它会触发 Just False

原因是我展示了一个虚拟键盘,它通常取决于任何按下或释放键的事件。对于dynMaybeShowNumbers,我简单地过滤掉了两个需要按住以显示虚拟小键盘的相关键。

我可以轻松编写更简单的代码,其中 dynShowNumbers :: Dynamic t Bool 不依赖于上面的 Dynamic t (Maybe Bool)

但是:

在这种情况下,只要按下任何键,我就会 dynShowNumbers 触发:

False---False---False------False--True---True----False----False----...

而上面的代码会导致

False-----------------------------True-----------False-------------...

对于相同的输入。

我觉得,我需要上面的行来避免动态重新渲染我的虚拟键盘——即使没有任何变化。


但是上面这行是好的做法吗?库中是否有有效的功能(找不到)?它类似于从列表中删除重复项的任务。

你有几个选择!在 Reflex.Dynamic 中,您可以使用这些 hold 变体:

-- | Create a new 'Dynamic' that only signals changes if the values actually
-- changed.
holdUniqDyn :: (Reflex t, MonadHold t m, MonadFix m, Eq a) => Dynamic t a -> m (Dynamic t a)

-- | Create a new 'Dynamic' that changes only when the underlying 'Dynamic'
-- changes and the given function returns 'False' when given both the old and
-- the new values.
holdUniqDynBy :: (Reflex t, MonadHold t m, MonadFix m) => (a -> a -> Bool) -> Dynamic t a -> m (Dynamic t a)

Reflex.Dynamic.Uniq 中似乎有一个更有原则的 type-based 方法。整个模块都专注于此类情况。