【发布时间】:2017-04-12 20:02:56
【问题描述】:
GHC 8 提供来自GHC.Stack 模块的HasCallStack,它允许函数在调用时请求记录堆栈帧。它还提供了withFrozenCallStack 函数,该函数“冻结”调用堆栈,因此不能再向其中添加任何帧。
在简单的场景中,这可以按我的预期工作。例如:
ghci> let foo :: HasCallStack => CallStack
foo = callStack
ghci> foo
[("foo",SrcLoc {srcLocPackage = "interactive", srcLocModule = "Ghci2", srcLocFile = "<interactive>", srcLocStartLine = 8, srcLocStartCol = 1, srcLocEndLine = 8, srcLocEndCol = 4})]
ghci> withFrozenCallStack foo
[]
当我正常调用foo 时,我得到一个堆栈帧,但是当我用withFrozenCallStack 包装它时,我没有。完美的。然而,当这个例子稍微复杂一点时,它就不再像我预期的那样表现了:
ghci> let foo :: CallStack
foo = bar
bar :: HasCallStack => CallStack
bar = callStack
ghci> foo
[("bar",SrcLoc {srcLocPackage = "interactive", srcLocModule = "Ghci9", srcLocFile = "<interactive>", srcLocStartLine = 24, srcLocStartCol = 11, srcLocEndLine = 24, srcLocEndCol = 14})]
ghci> withFrozenCallStack foo
[("bar",SrcLoc {srcLocPackage = "interactive", srcLocModule = "Ghci9", srcLocFile = "<interactive>", srcLocStartLine = 24, srcLocStartCol = 11, srcLocEndLine = 24, srcLocEndCol = 14})]
通过添加这个简单的间接层,尽管我使用了withFrozenCallStack,堆栈帧仍然被包含在内。为什么?
从概念上讲,我对HasCallStack 的理解是,它就像在当前调用堆栈上隐式使用pushCallStack,而pushCallStack 对冻结的调用堆栈没有影响。那么,为什么withFrozenCallStack 不阻止将上述堆栈帧添加到调用堆栈中呢?
【问题讨论】: