出于某种原因,我需要欺骗Haskell执行一个无限循环,而不是仅仅检测它并退出<<loop>>,但它太聪明了.是否有任何方便的例子,其中循环是由严格注释(!)引起的,还是我可以关闭循环检测?目前我在做
x = x + y
y = x + y
inf !n = 0
main = do
print $ inf x
Run Code Online (Sandbox Code Playgroud)
GS *_*ica 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
Run Code Online (Sandbox Code Playgroud)
在我添加if它之前,GHC确实似乎非常聪明地发现循环,甚至发现了递归函数调用.
我-O3在GHC 7.10上测试了这个.
编辑:添加了fun提问者建议的额外功能,只是为了满足涉及爆炸模式的要求.它与循环本身并不真正相关.此外,从改变Integer到Int另一个答案的建议,以确保持续的内存使用情况.
"问题"是当ghc正在评估thunk时,它会用黑洞替换它.这就是为什么类似以下简单示例的东西不起作用的原因:
inf :: ()
inf = inf
main :: IO ()
main = return $! inf
Run Code Online (Sandbox Code Playgroud)
Ghc将强制inf,这将导致它第二次强制inf.它将实现inf被黑洞并检测到一个循环.
提出无限计数器的解决方案将起作用,但会为整数计数器分配越来越多的内存.它可能无关紧要,因为Integer的内存是对数的,但使用Int可能会稍微优雅,只需让计数器换行.
另一种选择是使用无限数据结构.这将创建垃圾,但在稳定状态下消耗固定数量的已分配内存.就像是:
main :: IO ()
main = return $! last $ repeat ()
Run Code Online (Sandbox Code Playgroud)