6

我正在使用 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 秒。

4

1 回答 1

2

对于很多这样的答案,“正确”或“合法”取决于您希望您的应用程序做什么。“惯用语”可能是一个更有趣的问题,但随着图书馆作者的去世,很难明确回答这些问题。因此,以下仅代表我的经验,可能不正确:

  1. 其中的“不安全”部分Control.Wire.Unsafe.Event是您将及时处理离散实例的想法,并且您可能不一定会保留程序所期望的连续时间语义。特别是,在模拟中发生的事件与时间状态(sin )之间没有区别(从类型的角度来看) Wire s e m a b,表示为 an Integervs a Float,因此您必须小心确保您正在做的事情感觉您的应用程序。包含的通用组合器在使用任何合理的“时间”定义时没有这种风险。从以下文档data Event

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

    从自述文件:

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

  2. 这样做当然没有什么“非法”的。何时禁止完全取决于您的应用程序。主要区别在于,如果您编写抑制的线,则抑制会“冒泡”到处理它的第一条线(例如使用Alternative: (<|>))。NoEvent如果没有活动,制作就可以了。:) 您正在寻找的行为可能会更好地使用现有的组合器进行建模dropWhileEfmap尽管如此Control.Wire.Event

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

    它不应该连续循环,直到会话中的时间比事件进入时长 5 秒。

    将需要一些东西来跟踪这个计时器,所以你不会绕过以一种或另一种容量的循环。(也许您可以让操作系统通过调用sleep或其他方式来执行此操作,但在内部某处仍有一些循环......)netwire让您可以显式地建模系统的行为并响应这些类型的事件:网络事件和计时器事件。因为 Haskell 是惰性的,所以如果你编写的连线使得“非常复杂的连线”依赖于一个计时器,那么“真正复杂的连线”的结果将在计时器到期之前不会被评估(参见after.)

于 2018-09-23T22:09:35.360 回答