Haskell HasCallStack 意外行为

fgh*_*ini 5 haskell stack-trace ghc

以下是我们拥有的一个非常常见的模式的简化,其中您有一些重试组合器包装 IO 操作。我想要一些堆栈跟踪,所以我添加了HasCallStack约束,但结果堆栈跟踪并不令人满意:

import Control.Monad (forM_)
import GHC.Stack

httpCall :: HasCallStack => IO ()
httpCall = do
  putStrLn $ prettyCallStack callStack
  print "http resolved"

retry :: HasCallStack => IO () -> IO ()
retry op =
  forM_ [1] $ \i ->
    op

main :: IO ()
main = retry httpCall
Run Code Online (Sandbox Code Playgroud)

堆栈跟踪:

CallStack (from HasCallStack):
  httpCall, called at main.hs:16:14 in main:Main
"http resolved"
Run Code Online (Sandbox Code Playgroud)

我假设HasCallStack约束得到解析main以适应参数类型,retry所以我将约束添加到参数类型:

CallStack (from HasCallStack):
  httpCall, called at main.hs:16:14 in main:Main
"http resolved"
Run Code Online (Sandbox Code Playgroud)

现在堆栈跟踪还有 2 个条目,它们都非常令人惊讶:

CallStack (from HasCallStack):
  httpCall, called at main.hs:17:14 in main:Main
  op, called at main.hs:14:5 in main:Main
  retry, called at main.hs:17:8 in main:Main
"http resolved"
Run Code Online (Sandbox Code Playgroud)

问题

  1. httpCall报告它是从main(第 17 行)调用的
  2. op 报告正确的行,但在开始的堆栈跟踪中看到它是非常意外的。

我预计会出现以下情况:

CallStack (from HasCallStack):
  httpCall, called at main.hs:14:5 in main:Main
  retry, called at main.hs:17:8 in main:Main
"http resolved"
Run Code Online (Sandbox Code Playgroud)