2012-03-13 20 views
3

我有以下功能:禁止運行時錯誤「無可辯駁的模式失敗模式Data.Maybe.Just B」

loopMyQ s q m = forever $ do 
     q' <- atomically $ readTVar q 
     let Just b = PSQ.findMin q' --irrefutable pattern here in case the queue has just been created 
      duetime = (PSQ.prio b) + 2.000 
     now <- getPOSIXTime 
     when (now > duetime) (transMit2 s now q m) 

的問題是,當PSQ有「剛」被創建爲空PSQ正義無法匹配,並在運行時給我一個無可辯駁的模式錯誤。這隻發生一次,因爲顯然後面的隊列被填滿,而且b總是匹配。

我試圖測試隊列是否爲空,然後在我的函數中對其執行操作,但是這使得整個事件運行速度降低了一倍。

由於這顯然不會傷害,所以這個錯誤可以用某種方式抑制,一個編譯器選項,還是我需要捕捉異常,然後忽略它(這也可能需要額外的時間)。

+1

不要擔心***可能會花費額外的時間。編寫正確的,檢查過的代碼並對其進行配置。如果檢查是減慢代碼的速度,那就對其進行處理。不成熟的優化是萬惡之源。 – rampion 2012-03-13 16:56:28

+2

我想你需要解釋更多關於失敗的模式匹配如何不會受到傷害。例如,值得一提的是'loopMyQ'(正如你在另一條評論中所說的那樣)是在'forkIO'的線程內部開始的,假如這個線程在拋出異常的時候死掉了,那麼可以這麼說。我懷疑你在其他解決方案中看到的放緩與你的其他線程在做什麼比在這裏發生的更多。 – 2012-03-14 00:15:09

+0

@rampion,benmachine謝謝,您的評論讓我走上了正確的道路。通過分析發現,loopMyQ中的永久循環運行的頻率與CPU可以做的一樣頻繁,並且每200毫秒執行一次動作。雖然對我來說,只需每200毫秒運行一次,並在需要時採取一些措施。 – 2012-03-14 12:48:42

回答

9

你可能使用retry 如果隊列爲空更好:在STM動作將不會重試,直到TVar隊列已更新!

loopMyQ s q m = forever $ do 

     b <- atomically $ do q' <- readTVar q 
          case PSQ.findMin q' of 
           Just b -> return b 
           Nothing -> retry 

     let duetime = (PSQ.prio b) + 2.000 
     now <- getPOSIXTime 
     when (now > duetime) (transMit2 s now q m) 
+0

我發現了許多與此類似的解決方案。在執行時間和速度方面都毫無喜感。以上三倍執行時間...。 – 2012-03-13 14:32:03

+0

@JFritsch聽起來像你有「正確」和「快速」之間的選擇。謹慎選擇。 – 2012-03-13 14:41:00

+0

@DanielWagner我仍然希望有人提出類似'{ - #不要打印f *運行時錯誤作爲終端輸出# - ''''' – 2012-03-13 15:12:26

5

假設一旦你的隊列非空,它將永遠不會再次爲空,你可以做的一件事是做昂貴的版本(檢查非空),直到它變爲非空,然後切換到便宜的版本。

loopMyQ s q m = do 
    q' <- atomically $ readTVar q 
    case PSQ.findMin q' of 
     Nothing -> loopMyQ s q m 
     Just b -> do 
     body b 
     forever $ do 
      q' <- atomically $ readTVar q 
      let Just b <- PSQ.findMin q' 
      body b    
    where body b = do 
    let duetime = 2 + PSQ.prio b 
    now <- getPOSIXTime 
    when (now > duetime) (transMit2 s now q m) 
+0

工程, - 只是發現在實踐中可能會有更多的條件,隊列運行空。有沒有辦法壓制/ **完全忽略**這樣的運行時錯誤?例如。使用PatternMatchFail? – 2012-03-13 07:56:24

+2

您可以使用[Control.Exception]捕獲運行時錯誤,例如模式匹配失敗(http://www.haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/Control-Exception .html#v%3ADenormal),但是這個_will_會讓你的代碼有問題(因爲執行的順序),很難維護,而且是單向的,它必須存在於'IO' monad中,因爲你只能捕獲那些錯誤。使用這樣的機器而不是簡單地使用模式匹配就是完全錯誤的:) – danr 2012-03-13 08:25:02

+0

J Fritsch:爲什麼不改變你的其他代碼來在'q'中存儲非空隊列? – rampion 2012-03-13 11:51:36