【问题标题】:Use of `periodic` in NetWire 5在 NetWire 5 中使用 `periodic`
【发布时间】:2015-05-03 08:16:16
【问题描述】:

考虑以下代码:

-- this defines what our 'state' will be
data Direction = North | East | South | West deriving (Eq, Show, Enum)
data State = State Int Bool Direction deriving (Show)

initialState :: State
initialState = State 0 True North

-- a simple routine to change a state and count the number of
-- changes
nextState :: State -> State
nextState (State i _ West) = State (i+1) False South
nextState (State i _ North) = State (i+1) True East
nextState (State i b s) = State i b $ (if b then succ else pred) s

-- a wire with local state
stateWire :: Wire s () m a State
stateWire = stateWireFrom initialState
  where
    stateWireFrom s = mkSFN $ \_ -> (nextState s, stateWireFrom (nextState s))

-- let's run the wire!
main = testWire clockSession_ stateWire 

您可以想象,testWire 将尽可能快地运行线路并将输出打印到屏幕上。但是,如果我想每 2 秒运行一次电线怎么办?查看文档,periodic 可能是解决方案:

-- Since periodic generates events, asSoonAs is used to 'unwrap' the Event
main = testWire clockSession_ (asSoonAs . periodic 2 . stateWire)

几乎有效。输出似乎是静态的大约 2 秒,但是当它更新时,很明显,当输出停止时,电线正在运行。也许我应该反过来做?

-- Now, this does make more sense to me...
main = testWire clockSession_ (stateWire . periodic 2)

但是,最终结果与我的第一次尝试完全一样。我在这里错过了什么?

编辑:请参阅 this answer 以获取已接受答案的(劣质)替代方案。

【问题讨论】:

  • 我建议您将您的编辑作为答案发布;在 stackoverflow 上允许回答您自己的问题,并且比将答案放入问题中更有意义。另外,可能没有必要复制我的答案,除非您想强调它们之间的一些区别。

标签: haskell netwire


【解决方案1】:

问题似乎在于您将stateWire 视为连续的电线,但它实际上应该是事件电线本身。假设我正确理解了您的意图,它可能应该是 accumE (flip $ const nextState) initialState - 有关 accumE,请参阅 the event docs - 然后您可以像这样使用它:

stateWire . periodic 2(反之不行)。

您的原始版本不起作用的原因是periodic 在没有事件时不会抑制,它只会产生一个NoEvent 值。而且由于您的 stateWire 只是忽略了它的输入,因此当周期性线在前面时,是否产生事件对其没有任何影响,而将周期性线放在后面只是意味着“定期捕获当前的快照state',这也不是你想要的。

注意:上一段中的“前”和“后”是指执行顺序,而不是源代码中的布局,如果使用.组合子,则相反。

【讨论】:

  • 我猜你的意思是accumE (flip $ const nextState) initialState。这行得通,但它让我意识到,如果我用when occurred 过滤它,我可以让它用连续的电线工作。
  • 是的,这是一个错字。现在修好了。这需要 Unsafe.Event 和恕我直言,取决于事件的状态更改(应该)肯定是事件本身。这样做你会突然得到一条声称是连续的线,但实际上不会产生任何间隔的值。
  • 你是对的。在事件中思考似乎确实是为这个问题建模的正确方法。另外,根据您的反馈编辑了我的问题。谢谢!
【解决方案2】:

作为已接受答案的替代方案,也可以过滤掉NoEvent,而无需更改线路:

main = testWire clockSession_ (stateWire . when occurred . periodic 2)

这种情况下,wire会改变状态,抑制2秒然后再改变。

另一个(接受的)答案不同:电线将改变状态,然后继续产生相同的结果 2 秒,然后再次改变它。

【讨论】:

    猜你喜欢
    • 2015-12-21
    • 1970-01-01
    • 1970-01-01
    • 2014-07-06
    • 1970-01-01
    • 2013-04-02
    • 2021-03-21
    • 1970-01-01
    • 2013-12-18
    相关资源
    最近更新 更多