如何从带HasCallStack约束的异常类型中无需开启profiling提取调用栈
问题1:当前写法能否提取到调用栈
你给出的现有定义无论是否开启profiling,都无法提取到调用栈。
放在数据构造器上的HasCallStack约束仅要求构造AException时当前上下文存在可用的调用栈,但不会自动将调用栈持久化存储到异常值中,构造完成后栈信息就会丢失,后续无法访问。HasCallStack本身是GHC的编译时特性,和profiling无关,不需要开启profiling即可使用。
问题2:自动填充调用栈的实现方案
你提到的显式添加CallStack字段的方案是目前的标准实现,你可以配合智能构造器实现自动填充,不需要每次构造时手动传参:
import GHC.Stack (CallStack, HasCallStack, callStack) import Data.Typeable (Typeable) import Control.Exception (Exception) -- 异常类型显式存储CallStack字段 data AException = AException !String !Int !CallStack deriving (Typeable, Exception) -- 智能构造器:加HasCallStack约束,自动捕获当前调用栈填充 mkAException :: HasCallStack => String -> Int -> AException mkAException msg code = AException msg code callStack
使用时只要调用mkAException构造异常,不需要手动传入调用栈,GHC会自动将构造点的调用栈填充到字段中。如果需要自动打印调用栈,可以手动实现Show实例:
instance Show AException where show (AException msg code stack) = mconcat [ "AException: " , msg, " 错误码: ", show code, "\n" , "调用栈:\n", show stack ]
如果要保证所有异常都带调用栈,只需要不导出AException的原始构造器,仅导出mkAException即可,不需要额外的模板代码或者profiling支持。
内容的提问来源于stack exchange,提问作者carbolymer
相关产品推荐
相关产品推荐

