首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用CallStack抛出异常?

如何用CallStack抛出异常?
EN

Stack Overflow用户
提问于 2019-01-02 00:00:44
回答 1查看 448关注 0票数 4

我有异常类型UnknownException,当抛出CallStack时,我希望包含它。

代码语言:javascript
复制
module Main where

import Control.Exception (Exception, throw)

newtype UnknownException = UnknownException
  { caller :: String
  } deriving (Show)

instance Exception UnknownException

main :: IO ()
main = willThrow

willThrow :: IO ()
willThrow = throw $ UnknownException "willThrow"

我想用上面的例子来打印这样的日志

代码语言:javascript
复制
example-exe: UnknownException {caller = "willThrow"}
CallStack (from HasCallStack):
  willThrow, called at app/Main.hs:16:13 in main:Main
  main, called at app/Main.hs:13:8 in main:Main

但实际上印刷:

代码语言:javascript
复制
example-exe: UnknownException {caller = "willThrow"}

另外,在Haskell中的异常中包含CallStack是一个很好的实践吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-02 00:38:46

是的,我认为这是很好的练习。如果您正在使用概要分析进行编译,则只需使用

代码语言:javascript
复制
currentCallStack :: IO [String]

来自GHC.Stack。注意,它在IO中,但是如果您使用的是纯代码,那么当您抛出错误时,我会认为unsafePerformIO很好。因为所有的底部都是平等的,所以没有任何违反纯度的行为。

但是,如果您想在没有分析的情况下获得调用堆栈(假设您希望将其包含在生产日志消息中),那么您必须做更多的工作。您必须在希望报告堆栈的任何地方都包含HasCallStack约束。所以

代码语言:javascript
复制
main :: IO ()
main = print f

f :: Int
f = g

g :: HasCallStack => Int
g = h

h :: HasCallStack => Int
h = error (show callStack)

将调用堆栈报告到g,但将省略f。可悲的是,

如果作用域中没有CallStack,并且封闭定义具有显式类型签名,则GHC将解决仅包含当前调用站点的单例CallStack的HasCallStack约束。

这意味着它将忽略任何f的调用者,即使他们确实拥有HasCallStack,仅仅因为f没有这样的约束。我觉得这太麻烦了。这是一个相当新的特性,所以我希望GHC团队有一个更好的想法,他们使用这个来走向。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53999891

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档