如何使用Haskell超时功能(在System.Timeout中)停止失控计算?

Pet*_*hte 9 haskell timeout infinite infinite-loop

System.Timeout中的超时功能有时无法停止无限计算。

例如,

timeout 1000 $ print $ length [0..]
Run Code Online (Sandbox Code Playgroud)

Nothing由于超时中断了无限计算,因此按预期返回。但

timeout 1000 $ print $ length $ cycle [1,2,3]
Run Code Online (Sandbox Code Playgroud)

永远循环。

在Mac上,使用ghc或ghci 8.6.4。

我希望第二个示例的行为与第一个示例相同,在1毫秒后中断无限计算并返回Nothing。而是,第二个示例挂起。

Wil*_*ess 4

您可以使用您自己的非共享实现cycle

> _Y g = g (_Y g)
_Y :: (t -> t) -> t

> take 10 . _Y $ ([1,2,3] ++)
[1,2,3,1,2,3,1,2,3,1]
it :: Num a => [a]

> timeout 100000 . print . length . _Y $ ([1,2,3] ++)
Nothing
it :: Maybe ()
(0.11 secs, 152470624 bytes)
Run Code Online (Sandbox Code Playgroud)

_Y当然会分配一个无限的、不断增长的列表,cycle这与共享不同,共享相当于fix ([1,2,3] ++)在内存中创建一个实际的循环列表:

> timeout 100000 . print . length . fix $ ([1,2,3] ++)
<<<hangs>>>
Run Code Online (Sandbox Code Playgroud)

也可以看看: