使用严格注释将GHC引入无限循环

时间:2015-08-02 21:31:57

标签: haskell

出于某种原因,我需要欺骗Haskell执行一个无限循环,而不仅仅是检测它并退出<<loop>>,但它太聪明了。是否有任何方便的示例,其中循环是由严格性注释(!)引起的,还是我可以关闭循环检测?目前我在做

x = x + y
y = x + y
inf !n = 0

main = do
    print $ inf x

2 个答案:

答案 0 :(得分:10)

这应该这样做:

{-# LANGUAGE BangPatterns #-}
f :: Int -> Int
f x = if x >= 0 then f (x + 1) else 0

fun !n = 0

main = print $ fun $ f 0

GHC确实在发现循环时非常聪明,在我添加if之前它甚至发现了递归函数调用。

我在GHC 7.10上使用-O3对此进行了测试。

编辑:根据提问者的建议添加额外的函数fun,以满足涉及爆炸模式的要求。它与循环本身并不真正相关。如另一个答案所示,也从Integer更改为Int,以确保内存使用量不断增加。

答案 1 :(得分:6)

“问题”是当ghc正在评估thunk时,它会用黑洞替换它。这就是为什么类似以下简单示例的东西不起作用的原因:

register

Ghc将强制inf,这将导致它第二次强制inf。它会实现inf被黑洞化并检测到一个循环。

提出无限计数器的解决方案将起作用,但会为整数计数器分配越来越多的内存。它可能无关紧要,因为Integer的内存是对数的,但是使用Int并让计数器换行可能稍微优雅一些​​。

另一种选择是使用无限数据结构。这将创建垃圾,但在稳定状态下消耗固定数量的已分配内存。类似的东西:

inf :: ()
inf = inf

main :: IO ()
main = return $! inf