Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell “抑制运行时错误”;模式数据的无可辩驳模式失败。可能。仅b“;_Haskell - Fatal编程技术网

Haskell “抑制运行时错误”;模式数据的无可辩驳模式失败。可能。仅b“;

Haskell “抑制运行时错误”;模式数据的无可辩驳模式失败。可能。仅b“;,haskell,Haskell,我有以下功能: 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

我有以下功能:

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)
loopMyQ s q m=forever$do

假设你的队列一旦变为非空,就再也不会变为空,你可以做的一件事就是只做昂贵的版本(检查非空),直到它变为非空,然后切换到便宜的版本

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)
loopMyQ s q m=do

q'使用 如果队列为空:在更新
TVar
中的队列之前,不会重试
STM
操作

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)
loopMyQ s q m=forever$do
返回
无->重试
让duetime=(PSQ.prio b)+2.000
现在是决斗时间(传输2 s现在是q m)

Works,-刚刚发现在实践中,队列运行为空的情况可能更多。是否无法抑制/完全忽略此类运行时错误?例如,使用PatternMatchFail?您可以使用捕获运行时错误,例如模式匹配失败,但这会使您的代码出现错误(因为执行顺序),难以维护,不规则,并且它必须存在于
IO
monad中,因为您只能在那里捕获这些错误。使用这样的机制而不是简单地使用模式匹配是完全错误的:)J Fritsch:为什么不改变您的其他代码,只在
q
中存储非空队列?外部循环“loopMyQ”看起来像是一个繁忙的等待。您应该将测试和“重试”调用放在第一个原子内部。然而,目前的TVar设计仍然感觉不对劲。我发现了许多类似的解决方案。在执行时间和速度方面都没有乐趣。上述操作将执行时间增加了三倍@JFritsch听起来像是在“正确”和“快速”之间进行选择。仔细选择。@DanielWagner我仍然希望有人能想出类似“{-#不要将f*运行时错误打印为终端输出#-}”这样的建议@JFritsch:有趣的是,您的代码在
重试时运行得较慢。我猜rampion的投票会慢一些。您有更大的代码片段可以测试吗?无论如何,仅仅是超出错误输出将不会帮助您的原始代码:
loopMyQ
如果没有
b
中绑定的
just b
@JFritsch,那么与其他实现相比,执行将增加三倍?至于
重试
,这是非常有效的,因为在它读取的
TVar
之一发生更改之前,中止的事务不会再次尝试。通过使用更细粒度的
TVar
s,您可能可以恢复一些速度,这样
retry
就有了更细粒度的信息,可以知道何时有机会成功。不要担心可能会花费额外的时间。编写正确的、经过检查的代码,并对其进行分析。如果检查是导致代码慢下来的原因,那么就处理它。过早的优化是万恶之源。我认为你需要更多地解释失败的模式匹配如何不会带来伤害。例如,值得一提的是,
loopMyQ
是(如您在另一条评论中所述)在一个带有
forkIO
的线程中启动的,如果抛出异常时该线程死亡,这大概是可以的。我怀疑您在其他解决方案中看到的减速更多地与您的其他线程所做的事情有关,而不是与这里发生的事情有关。@rampion,benmachine谢谢,您的评论让我走上了正确的道路。通过分析,我发现loopMyQ中的forever循环尽可能频繁地运行,并且每200毫秒执行一次操作。而对我来说,每200毫秒运行一次就足够了,如果需要的话,还可以执行一些操作。