循环不终止

时间:2012-03-05 23:15:09

标签: haskell

下面的函数要么接收并确认要么等到它的到期时间到来并返回。

现在,它在接收和确认时有效。当没有收到确认时它会正常工作并等到适当的时间。

到达到期时间时冻结。似乎它没有正确退出我的自构造循环。我也试过if-then-else,但结果相同。我不想使用whileM。

如何正确退出循环?

import Network.Socket hiding (send, sendTo, recv, recvFrom)
import Network.Socket.ByteString


waitAck s duetime' = do
      print ("in")
      (a, _) <- recvFrom s 4711
      now' <- getPOSIXTime
      unless (B.unpack a == "ack") (when (now' < duetime') (waitAck s duetime'))
      print (B.unpack a)
      return ()

2 个答案:

答案 0 :(得分:4)

正确的解决方案是竞争两个线程,一个等待确认,一个等待时间。杀死失去种族的人。也许这个(未经测试的)代码会给你一个关于如何:

的提示
import Control.Concurrency.MVar

withTimeout :: Int -> IO a -> IO (Maybe a)
withTimeout n io = do
    mvar    <- newEmptyMVar
    timeout <- forkIO (threadDelay n >> putMVar mvar Nothing)
    action  <- forkIO (io >>= putMVar mvar . Just)
    result  <- takeMVar mvar
    killThread timeout
    killThread action
    return result

waitAck s timeout = withTimeout timeout go where
    go = do
        (a, _) <- recvFrom s 4711
        if B.unpack a == "ack" then print (B.unpack a) else go

编辑:似乎base提供System.Timeout.timeout就是为了这个目的。它的实现也比这个更正确。

答案 1 :(得分:1)

这不是一个迭代循环。在递归调用之后,你不会在这些东西上放置任何条件,所以当条件最终失败时,整个事情将展开,为每次递归调用打印一次。我怀疑这可能足以使它显得冷冻。

尝试这样的事情:

waitAck s duetime' = do
    print ("in")
    (a, _) <- recvFrom s 4711
    now' <- getPOSIXTime
    if B.unpack a == "ack" || now' >= duetime'
        then print (B.unpack a)
        else waitAck s duetime'