Haskell NetWire 5中“periodic”的用法

Haskell NetWire 5中“periodic”的用法,haskell,netwire,Haskell,Netwire,考虑以下代码: -- 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 routin

考虑以下代码:

-- 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秒运行一次电线呢?查看文档,
定期
可能是解决方案:

-- 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)
然而,最终的结果和我第一次尝试完全一样。我错过了什么


编辑:请参阅,以获得可接受答案的(较差的)备选答案。

问题似乎在于,您将您的
状态线
视为一条连续线,但它本身确实应该是一条事件线。假设我正确理解了您的意图,它可能应该是
acume(flip$const nextState)initialState
-请参阅accumE-然后您可以这样使用它:

stateWire。周期2(另一种方法不起作用)

原始版本不起作用的原因是
periodic
在没有事件的情况下不会禁用,它只会生成一个
NoEvent
值。由于您的stateWire只会忽略其输入,因此当周期性连线在前面时,是否生成事件对它没有任何影响,而将周期性连线放在后面只是意味着“定期捕捉当前状态的快照”,这也不是您想要的


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

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

main = testWire clockSession_ (stateWire . when occurred . periodic 2)
在这种情况下,导线将改变状态,抑制2秒,然后再次改变


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

我猜你的意思是
accumE(flip$const nextState)初始状态
。这是可行的,但它让我意识到,如果我在发生时用
过滤它,我可以让它在连续的电线上工作。现在修好了。这需要safe.Event和IMHO。依赖于事件的状态更改肯定是(应该是)事件本身。像这样做,你会突然得到一条声称是连续的线,但实际上不会产生任何间隔的值。你是对的。在事件中思考似乎是模拟这个问题的正确方法。另外,根据您的反馈编辑了我的问题。谢谢我建议你将你的编辑作为答案发布;在stackoverflow上可以回答您自己的问题,这比将答案放入问题中更有意义。此外,可能没有必要重复我的答案,除非你想强调它们之间的一些区别。