use*_*438 6 random monads haskell timeout lazy-evaluation
我想用Haskell评估随机计算,并使用Control.Monad.Random库超时.以下工作正常:
ghci> import System.Timeout
ghci> import Control.Monad.Random
ghci> timeout 1000 . evalRandIO $ getRandomR (True, False)
Just True
Run Code Online (Sandbox Code Playgroud)
但是,如果我们有一个Rand StdGen a永不终止的类型计算(即评估到底部),这种方法似乎不起作用.例如:
ghci> let f = f :: Rand StdGen Bool
ghci> timeout 1000 $ evalRandIO f
Just
Run Code Online (Sandbox Code Playgroud)
在这里GHCI打印"Just",然后无限期地挂起试图评估f.能否了解Haskell运行时的人比我更能解释为什么会这样,以及如何解决它?我的猜测是表达式evalRandIO f被评估为WHNF,因此timeout 10认为计算将终止,但我真的不知道.
如果你做某些事情,这可能会更有意义
> Just x <- timeout 1000 $ evalRandIO f
> :t x
x :: Bool
> x
Interrupted.
Run Code Online (Sandbox Code Playgroud)
计算本身正在完成,即它到达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
Run Code Online (Sandbox Code Playgroud)
您将看到它挂起一秒钟,然后Nothing在deepseq未完成评估时返回,f以便它可以执行return f.
所以,是的,你的问题源于f = f被评估为WHNF而不是NF 的事实.为了强制NF,你需要使用类似的东西deepseq.另一个可能更简单的例子就是使用$!运算符,例如:
> let f :: Rand StdGen Bool
| f = f
|
> timeout 1000000 $ evalRandIO $! f
Nothing
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
115 次 |
| 最近记录: |