出于某种原因,我需要欺骗Haskell执行一个无限循环,而不仅仅是检测它并退出<<loop>>
,但它太聪明了。是否有任何方便的示例,其中循环是由严格性注释(!
)引起的,还是我可以关闭循环检测?目前我在做
x = x + y
y = x + y
inf !n = 0
main = do
print $ inf x
答案 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