我正在使用这个工具,用户可以在[config files |中定义 - 并包含它内容文本文件|他们自己的&#34;模板&#34; (像胡子等),这些可以引用其他人,因此他们可以诱导循环。正当我即将创建一个&#34; max-loops&#34;设置我用runghc实现了程序一段时间之后只退出了<<loop>>
的告别消息。这对我来说实际上已经足够好了但引起了一些争议:
GHC或运行时如何实际检测到它被卡在一个循环中,它如何区分所需的长时间运行操作和偶然的无限循环?暂停问题仍然是我检查的最后一件事..
可以自定义设置给编译器或运行时的任何(时间或迭代)限制吗?
是runghc
- 仅在所有最终编译输出中是否存在?
在构建版本时,如果稍后设置-o
(优化)标志会禁用这种明显的内置循环检测吗?
所有的东西我当然可以找出困难的方法,但谁知道也许有人已经更详细地研究了这个...(很难为"haskell" "<<loop>>"
google / ddg,因为他们剥去尖括号然后显示结果&#34;如何在Haskell&#34;等循环。)
答案 0 :(得分:5)
这是在GHC中实现的STG运行时的简单“改进”。我会分享我所理解的内容,但GHC专家可能会提供更有用和准确的信息。
GHC在完成多项优化后编译成一种名为Core的中间语言。您可以使用ghc -ddump-simpl ...
非常粗略地说,在Core中,未评估的绑定(如let x = 1+y+x in f x
)会产生一个thunk。一些内存被分配到某个地方来表示闭包,x
被指向它。
当x
强制{和{{}} f
时,将评估thunk。以下是改进:在评估开始之前,x
的thunk被一个名为BLACKHOLE
的特殊值覆盖。在评估x
之后(对WHNF),黑洞再次被实际值覆盖(因此我们不会重新计算它,例如f x = x+x
)。
如果强行黑洞,则会触发<<loop>>
。这实际上是一个IO异常(那些也可以在纯代码中引发,所以这很好)。
示例:
let x = 1+x in 2*x -- <<loop>>
let g x = g (x+1) in g 0 -- diverges
let h x = h (10-x) in h 0 -- diverges, even if h 0 -> h 10 -> h 0 -> ...
let g0 = g10 ; g10 = g0 in g0 -- <<loop>>
请注意,h 0
的每次调用都被认为是一个明显的thunk,因此不会强迫黑洞。
棘手的部分是,理解哪些thunk实际上是在Core中创建并不是完全无足轻重的,因为GHC可以在发布Core之前执行多次优化。因此,我们应该将<<loop>>
视为奖励,而不是GHC的给定/硬性保证。未来的新优化可能会将某些<<loop>>
替换为实际的非终止。
如果你想谷歌的东西,“GHC,blackhole,STG”应该是很好的关键词。