【问题标题】:Why does HasCallStack still add stack frames when using withFrozenCallStack?为什么在使用 withFrozenCallStack 时 HasCallStack 仍会添加堆栈帧?
【发布时间】: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 不阻止将上述堆栈帧添加到调用堆栈中呢?

【问题讨论】:

    标签: haskell callstack


    【解决方案1】:

    在您的代码中,fooCallStack 类型的静态值。请注意,它确实没有具有HasCallStack 约束。

    无论您如何以及在何处使用foo,它都将始终引用这个特定的CallStackfoo 本身是使用 bar 定义的,它使用 HasCallStack 机制并不重要——你可以静态定义 foo = [("bar",…

    尝试将HasCallStack =&gt; 添加到foo 的类型签名中。它现在的行为是否符合您的预期?

    【讨论】:

    • 啊,当然,这是有道理的。我对 Haskell 中隐式参数的直觉显然不是最好的,因为这适用于任何隐式参数,而不仅仅是HasCallStack。无论如何,谢谢。
    • 差不多,但不完全。使用普通的隐式参数,如果在停止使用约束的位置没有显式绑定它,则会出现错误。但是使用HasCallStack,编译器会检测到这一点并神奇地绑定初始调用堆栈。
    • 啊哈,是的,这是有道理的——你又是对的。 :) HasCallStack 的神奇本质肯定有点令人困惑。我仍然不认为我完全理解如何推断HasCallStack 约束的复杂性,但幸运的是,在实践中这对我来说似乎不是太大的问题,哈哈。
    • @AlexisKing 文档here 描述了这种特殊的魔法。
    猜你喜欢
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-19
    • 2015-10-04
    • 2011-10-30
    相关资源
    最近更新 更多