为什么HasCallStack在使用withFrozenCallStack时仍然添加堆栈帧?

Ale*_*ing 7 callstack haskell

GHC 8 HasCallStackGHC.Stack模块提供,它允许函数在被调用时记录请求堆栈帧.它还提供了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
[]
Run Code Online (Sandbox Code Playgroud)

当我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})]
Run Code Online (Sandbox Code Playgroud)

通过添加这个简单的间接层,尽管我使用了堆栈帧,但它仍然被包含在内withFrozenCallStack.为什么?

从概念上讲,我的理解HasCallStack是它就像是pushCallStack对当前调用堆栈的隐式使用,并且pushCallStack对冻结的调用堆栈没有影响.那么,为什么withFrozenCallStack不阻止将上面的堆栈帧添加到调用堆栈中?

Joa*_*ner 2

在您的代码中,foo是 type 的静态值CallStack。请注意,它没有约束HasCallStack

\n\n

无论您如何以及在何处使用foo,它总是指此特定的CallStackfoo使用它定义本身并不重要,bar它使用HasCallStack您可以静态定义的机器 \xe2\x80\x93foo = [("bar",\xe2\x80\xa6

\n\n

尝试添加HasCallStack =>foo\xe2\x80\x99s 类型签名。现在它的行为符合您的预期吗?

\n