使用Control.Wire.Unsafe.Event时我应该保留哪些不变量?

时间:2018-04-06 21:14:43

标签: haskell frp netwire

我正在使用Netwire编写一个由来自网络的事件驱动的程序。我想这里有三个问题:

  1. 是什么让Control.Wire.Unsafe.Event不安全?就像标题所说的那样,我需要保持哪些不变量才能安全地使用它?

  2. 我觉得我需要这样的东西:mapMaybeE :: Monad m => (a -> Maybe b) -> Wire s e m (Event a) (Event b)。上下文是我有来自网络的消息,我想只响应其中一些消息。这就是我写的:

    mapMaybeE :: Monad m => (a -> Maybe b) -> Wire s e m (Event a) (Event b)
    mapMaybeE f = arr go . arr (fmap f)
      where go WU.NoEvent = WU.NoEvent
            go (WU.Event Nothing) = WU.NoEvent
            go (WU.Event (Just a)) = WU.Event a
    

    这是"合法"?或者如果没有事件,我是否应该禁止?

  3. Netwire对这类问题有意义吗?我所见过的所有例子都是连续循环的游戏。在这里,我只想在有事情要做的时候踩电线。大多数情况下,这将是网络事件,但我可能也想在计时器上做事情。例如。一个事件进来,然后五秒钟后程序做了一些事情。它不应该不断循环,直到会话中的时间比事件进入的时间大5秒。

1 个答案:

答案 0 :(得分:0)

对于许多这样的答案,“正确”或“合法”取决于您希望应用程序执行的操作。 “惯用语”可能是一个更有趣的问题,但是随着图书馆作者的逝世,很难确定性地回答这些问题。因此,以下内容仅代表我的经验,可能并不正确:

  1. Control.Wire.Unsafe.Event的“不安全”部分是您将及时处理离散实例的想法,并且您不一定会保留程序期望的连续时间语义。特别是,在模拟中发生的事件与以s和{{表示的时间状态(在Wire s e m a b中的Integer)中发生的事件(从类型角度来看)没有区别。 1}},因此您必须注意确保所做的事情对您的应用程序有意义。所包括的通用组合器在使用任何“时间”的合理定义的意义上都没有这种风险。来自Float的文档:

      

    表示值流,每个值都与出现时间一起。由于事件通常用于功能性反应式编程,因此它并未定义大多数常用实例来保护连续时间和离散事件发生语义。

    自述文件:

      

    如果您是框架开发人员,则可以导入data Event模块来实现自己的事件。游戏引擎可能包括按键事件或场景中发生的某些事情。但是,作为应用程序开发人员,您应该将此类型视为不透明。为了保护连续的时间语义,这是必需的。您不能直接访问事件值。

  2. 以这种方式进行操作肯定没有任何“非法”行为。什么时候抑制完全取决于您的应用。关键区别在于,如果您编写抑制的导线,则抑制会“气泡化”到处理它的第一根导线(例如使用Control.Wire.Unsafe.EventAlternative)。如果没有事件,则产生(<|>)很好。 :)尽管如此,使用NoEvent中的现有组合器dropWhileEfmap可以更好地建模您想要的行为:

    Control.Wire.Event
  3. 是的,mapMaybeE :: Monad m => (a -> Maybe b) -> Wire s e m (Event a) (Event b) mapMaybeE = arr (fmap fromJust) . dropWhileE isNothing . arr (fmap f) 对于必须模拟具有时间相关语义的系统状态的任何问题都是有意义的。要扩展,

      

    在会话中的时间比事件进入时多五秒之前,不必连续循环。

    某些事情将需要跟踪此计时器,因此您不会绕过一个或多个容量的循环。 (也许您可以让操作系统通过调用netwire之类的东西来执行此操作,但是内部仍然有一些循环...)sleep使您可以显式地对系统的行为建模并做出响应这些类型的事件:网络事件和计时器事件。因为Haskell是惰性的,所以如果您编写连线时“真正复杂的连线”取决于计时器,则直到定时器到期(请参阅after。),才会评估“真正复杂的连线”的结果。