Haskell——在Rand单子中计时计算



我想使用Control.Monad.Random库评估Haskell中的随机计算超时。下面的代码可以正常工作:

ghci> import System.Timeout
ghci> import Control.Monad.Random
ghci> timeout 1000 . evalRandIO $ getRandomR (True, False)
Just True

然而,如果我们有一个类型为Rand StdGen a的计算永远不会终止(即求值到底部),这种方法似乎不起作用。例如:

ghci> let f = f :: Rand StdGen Bool
ghci> timeout 1000 $ evalRandIO f
Just

这里GHCI打印"Just",然后无限期挂起,试图评估f。谁能比我更了解Haskell运行时解释为什么会发生这种情况,以及如何绕过它?我的猜测是,表达式evalRandIO f被评估为WHNF,因此timeout 10认为计算将终止,但我真的不知道。

如果您要做像

这样的事情,这可能更有意义
> Just x <- timeout 1000 $ evalRandIO f
> :t x
x :: Bool
> x
Interrupted.

计算本身正在完成,即它达到了WHNF,所以timeout没有捕获它。timeout 1000函数本身完成并返回Just undefined可以timeout捕获底部求值的示例是

> import Control.DeepSeq
> :set +m    -- Multiline mode
> let f :: Bool
|     f = f
|
> timeout 1000000 $ deepseq f (return f)
Nothing

您将看到它挂起一秒钟,然后当deepseq没有完成f的计算时返回Nothing,因此它可以执行return f

所以,是的,你的问题是源于f = f被评估为WHNF而不是NF。为了强制NF,您需要使用deepseq之类的东西。另一个可能更简单的例子是只使用$!操作符,例如:

> let f :: Rand StdGen Bool
|     f = f
|
> timeout 1000000 $ evalRandIO $! f
Nothing

相关内容

  • 没有找到相关文章

最新更新