Haskell - 在Rand monad中计算出计算结果

时间:2014-07-24 14:45:28

标签: haskell random timeout monads lazy-evaluation

我想使用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认为计算将终止,但我真的不知道。

1 个答案:

答案 0 :(得分:5)

如果您要执行类似

的操作,这可能会更有意义
> 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

您会看到它挂起一秒钟,然后在Nothing未完成评估deepseq时返回f,以便它可以执行return f

所以是的,你的问题源于f = f被评估为WHNF而不是NF的事实。为了强制使用NF,您需要使用类似deepseq的内容。另一个可能更简单的例子就是使用$!运算符,例如:

> let f :: Rand StdGen Bool
|     f = f
|
> timeout 1000000 $ evalRandIO $! f
Nothing
相关问题