System.Timeout中的超时函数有时无法停止无限计算。
例如,
timeout 1000 $ print $ length [0..]
按预期返回Nothing
,因为超时会中断无限计算。但
timeout 1000 $ print $ length $ cycle [1,2,3]
永远循环。
这是在Mac上,使用ghc或ghci 8.6.4。
我希望第二个例子的行为与第一个一样,在1毫秒后中断无限计算并返回Nothing
。相反,第二个例子挂起。
您可以使用自己的,非共享的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)
_Y
当然会分配一个无限的,不断增长的列表,不像共享cycle
,它相当于fix ([1,2,3] ++)
,它在内存中创建一个实际的循环列表:
> timeout 100000 . print . length . fix $ ([1,2,3] ++)
<<<hangs>>>
也可以看看: