使用 Control.Wire.Unsafe.Event 时我应该保持哪些不变量?
What invariants am I supposed to maintain when using Control.Wire.Unsafe.Event?
我正在使用 Netwire 编写一个由网络事件驱动的程序。我想这里有三个问题:
是什么让 Control.Wire.Unsafe.Event
不安全?正如标题所说,我需要维护哪些不变量才能安全地使用它?
我决定我需要这样的东西: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
是"legal"吗?或者如果没有事件我应该抑制?
Netwire 对这类问题有意义吗?我见过的所有例子都是不断循环的游戏。在这里,我只想在有事情要做的时候踩线。大多数情况下,这将是网络事件,但我可能还想在计时器上做一些事情。例如。一个事件进来了,然后五秒钟后程序做了一些事情。它不应该连续循环,直到 session 中的时间比事件发生时多五秒。
对于其中的许多答案,"correct" 或 "legal" 取决于您希望应用程序执行的操作。 "Idiomatic" 可能是一个更有趣的问题,但由于图书馆作者已经去世,很难明确回答这些问题。因此,以下仅代表我的经验,可能不正确:
Control.Wire.Unsafe.Event
的 "unsafe" 部分是这样的想法,即您将及时处理离散实例,并且您可能不一定保留程序中的连续时间语义期望。特别是,在模拟中发生的时间状态(Wire s e m a b
中的 s
)表示为 Integer
与 Float
,所以你必须小心确保你所做的对你的应用程序有意义。包含的通用组合器没有这种风险,因为它们使用 "time" 的任何合理定义。来自 data Event
的文档:
Denotes a stream of values, each together with time of occurrence. Since Event is commonly used for functional reactive programming it does not define most of the usual instances to protect continuous time and discrete event occurrence semantics.
来自自述文件:
If you are a framework developer you can import the Control.Wire.Unsafe.Event
module to implement your own events. A game engine may include events for key presses or certain things happening in the scene. However, as an application developer you should view this type as being opaque. This is necessary in order to protect continuous time semantics. You cannot access event values directly.
那样做肯定没有什么"illegal"。何时抑制完全取决于您的应用程序。关键区别在于,如果您编写抑制线,抑制 "bubbles up" 到处理它的第一条线(例如 Alternative
:(<|>)
)。如果没有事件,生成 NoEvent
就可以了。 :) 使用 Control.Wire.Event
中的现有组合器 dropWhileE
和 fmap
可能会更好地模拟您正在寻找的行为:
mapMaybeE :: Monad m => (a -> Maybe b) -> Wire s e m (Event a) (Event b)
mapMaybeE = arr (fmap fromJust) . dropWhileE isNothing . arr (fmap f)
是的,netwire
对于您必须模拟具有时间相关语义的系统状态的任何问题都有意义。展开,
It shouldn't have to loop continuously until the time in the session is five seconds greater than when the event came in.
需要一些东西来跟踪这个计时器,所以你不会绕过一个或另一个容量的循环。 (也许你可以让操作系统通过调用 sleep
或其他方式来完成它,但在内部某处仍然存在一些循环......)netwire
允许你显式地模拟系统的行为并响应这些类型的事件:网络事件和定时器事件。因为 Haskell 是惰性的,如果您编写 "really complicated wire" 依赖于计时器的连线,则 "really complicated wire" 的结果在计时器到期之前不会被评估(请参阅 after
。)
我正在使用 Netwire 编写一个由网络事件驱动的程序。我想这里有三个问题:
是什么让
Control.Wire.Unsafe.Event
不安全?正如标题所说,我需要维护哪些不变量才能安全地使用它?我决定我需要这样的东西:
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
是"legal"吗?或者如果没有事件我应该抑制?
Netwire 对这类问题有意义吗?我见过的所有例子都是不断循环的游戏。在这里,我只想在有事情要做的时候踩线。大多数情况下,这将是网络事件,但我可能还想在计时器上做一些事情。例如。一个事件进来了,然后五秒钟后程序做了一些事情。它不应该连续循环,直到 session 中的时间比事件发生时多五秒。
对于其中的许多答案,"correct" 或 "legal" 取决于您希望应用程序执行的操作。 "Idiomatic" 可能是一个更有趣的问题,但由于图书馆作者已经去世,很难明确回答这些问题。因此,以下仅代表我的经验,可能不正确:
Control.Wire.Unsafe.Event
的 "unsafe" 部分是这样的想法,即您将及时处理离散实例,并且您可能不一定保留程序中的连续时间语义期望。特别是,在模拟中发生的时间状态(Wire s e m a b
中的s
)表示为Integer
与Float
,所以你必须小心确保你所做的对你的应用程序有意义。包含的通用组合器没有这种风险,因为它们使用 "time" 的任何合理定义。来自data Event
的文档:Denotes a stream of values, each together with time of occurrence. Since Event is commonly used for functional reactive programming it does not define most of the usual instances to protect continuous time and discrete event occurrence semantics.
来自自述文件:
If you are a framework developer you can import the
Control.Wire.Unsafe.Event
module to implement your own events. A game engine may include events for key presses or certain things happening in the scene. However, as an application developer you should view this type as being opaque. This is necessary in order to protect continuous time semantics. You cannot access event values directly.那样做肯定没有什么"illegal"。何时抑制完全取决于您的应用程序。关键区别在于,如果您编写抑制线,抑制 "bubbles up" 到处理它的第一条线(例如
Alternative
:(<|>)
)。如果没有事件,生成NoEvent
就可以了。 :) 使用Control.Wire.Event
中的现有组合器dropWhileE
和fmap
可能会更好地模拟您正在寻找的行为:mapMaybeE :: Monad m => (a -> Maybe b) -> Wire s e m (Event a) (Event b) mapMaybeE = arr (fmap fromJust) . dropWhileE isNothing . arr (fmap f)
是的,
netwire
对于您必须模拟具有时间相关语义的系统状态的任何问题都有意义。展开,It shouldn't have to loop continuously until the time in the session is five seconds greater than when the event came in.
需要一些东西来跟踪这个计时器,所以你不会绕过一个或另一个容量的循环。 (也许你可以让操作系统通过调用
sleep
或其他方式来完成它,但在内部某处仍然存在一些循环......)netwire
允许你显式地模拟系统的行为并响应这些类型的事件:网络事件和定时器事件。因为 Haskell 是惰性的,如果您编写 "really complicated wire" 依赖于计时器的连线,则 "really complicated wire" 的结果在计时器到期之前不会被评估(请参阅after
。)