You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Haskell中打印调用栈?求助解决实现失败问题

Fixing Call Stack Printing in Haskell-Language-Server

Let’s walk through why your current approach isn’t working and how to fix it:

Why Your Current Methods Aren’t Producing Output

  • traceStack: This function only appends a stack trace when an exception is thrown. Since putStrLn doesn’t throw an error, nothing gets logged here.
  • emptyCallStack: As the name suggests, this is an empty stack—calling getCallStack on it will always return an empty list.
  • currentCallStack: Without proper function annotations or compiler flags, this might return an incomplete or empty stack because GHC isn’t tracking the necessary stack info.

Required Compiler & Runtime Setup

First, update your .cabal file’s ghc-options for the executable to include these flags (in addition to -fprof-auto):

ghc-options:
  -fprof-auto
  -rtsopts
  -fprof-cafs
  • -rtsopts: Lets you pass runtime system (RTS) options when running the program.
  • -fprof-cafs: Enables profiling of constant applicative forms, which helps capture more complete stack traces.

When running HLS, use this command to ensure profiling is active and stack traces are enabled:

cabal run haskell-language-server-wrapper --enable-profiling --enable-executable-dynamic +RTS -xc
  • +RTS -xc: Forces GHC to print a stack trace whenever an exception is thrown—great for debugging crashes.

Corrected Code to Print Call Stacks

Modify your defaultMain function to use GHC’s proper call stack utilities. You’ll need to import GHC.Stack and add a HasCallStack constraint:

import GHC.Stack (HasCallStack, callStack, getCallStack, currentCallStack, traceStack)

defaultMain :: HasCallStack => Recorder (WithPriority Log) -> Arguments -> IdePlugins IdeState -> IO ()
defaultMain recorder args idePlugins = do
    -- Print stack using the HasCallStack annotation
    putStrLn "=== Call stack from HasCallStack ==="
    mapM_ print $ getCallStack callStack

    -- Print current stack via IO
    putStrLn "\n=== Current runtime call stack ==="
    stack <- currentCallStack
    mapM_ putStrLn stack

    -- Trigger a stack trace with traceStack (requires an exception)
    putStrLn "\n=== Exception stack trace ==="
    _ <- traceStack "Error context" $ error "Intentional error to show stack trace"
    exitFailure

Key Fixes:

  • HasCallStack constraint: This tells GHC to track the call stack up to defaultMain, making the callStack variable available.
  • getCallStack callStack: Uses the actual stack from the current context instead of an empty one.
  • Exception with traceStack: By throwing an error, you trigger traceStack to log the stack trace.

Extra Tips

  • If stacks are still incomplete, make sure all dependencies are built with profiling. Run this to rebuild everything with profiling flags:
    cabal build --enable-profiling --enable-executable-dynamic --ghc-options="-fprof-auto"
    
  • Remember to remove profiling flags for production builds, as they add overhead.

内容的提问来源于stack exchange,提问作者zichao liu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 23:06:15