2015-03-02 18 views
1

使用periodic`的`考慮下面的代碼:在NetWire 5

-- 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爲接受的答案(劣質)的替代方案。

+0

我建議您將編輯內容發佈爲答案;回答你自己的問題在stackoverflow上是允許的,比把答案放在問題上更有意義。另外,除非你想強調它們之間的一些區別,否則可能不需要複製我的答案。 – Cubic 2015-03-03 16:50:18

回答

1

這個問題似乎是你對待你的stateWire就好像它是連續的線,但它確實應該是一個事件線本身。假設我正確地理解了你的意圖,它應該是accumE (flip $ const nextState) initialState - 參見the event docs accumE - 那麼你可以像這樣使用它:

stateWire . periodic 2(其他方式不起作用)。

原始版本無法正常工作的原因是,periodic在沒有事件時不會抑制,而只會產生NoEvent值。而且由於你的stateWire只是忽略了它的輸入,所以當週期線位於前面時,無論是否產生事件都不會產生任何影響,而將週期線置於後面意味着「定期捕獲當前的快照狀態',這也不是你想要的。

:「前」和前一段的「返回」是指執行順序,而不是在源代碼中的佈局是相反,如果你使用.組合子。

+0

我想你的意思是'accumE(flip $ const nextState)initialState'。這有效,但它讓我意識到,如果我用'發生時'過濾它,我可以使它與連續電線一起工作。 – 2015-03-03 11:27:17

+1

是的,這是一個錯字。現在修復。 這需要不安全。事件和恕我直言,依賴於事件的狀態變化是(應該)當然是事件本身。這樣做你會突然發現一條聲稱是連續的線,但實際上並沒有產生任何間隔的值。 – Cubic 2015-03-03 15:29:52

+0

你說得對。在事件中思考真的似乎是對這個問題建模的正確方法。另外,根據您的反饋編輯我的問題。謝謝! – 2015-03-03 18:34:27

1

作爲替代接受的答案,它也可以以濾除NoEvent,在不改變線:

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

在這種情況下,導線會發生變化的狀態下,抑制2秒鐘然後再次更改它。

其他(接受的)答案的工作方式不同:線將改變狀態,然後繼續產生相同的結果,持續2秒然後再次更改。