How to throw an exception with CallStack?
I have Exception type UnknownException
, which I'd like to include the CallStack when it's thrown.
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"
I'd like the above example to print logs like this
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
but actually printed:
example-exe: UnknownException {caller = "willThrow"}
Also, is it a good practice to include CallStack in exceptions in Haskell?
haskell exception
add a comment |
I have Exception type UnknownException
, which I'd like to include the CallStack when it's thrown.
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"
I'd like the above example to print logs like this
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
but actually printed:
example-exe: UnknownException {caller = "willThrow"}
Also, is it a good practice to include CallStack in exceptions in Haskell?
haskell exception
add a comment |
I have Exception type UnknownException
, which I'd like to include the CallStack when it's thrown.
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"
I'd like the above example to print logs like this
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
but actually printed:
example-exe: UnknownException {caller = "willThrow"}
Also, is it a good practice to include CallStack in exceptions in Haskell?
haskell exception
I have Exception type UnknownException
, which I'd like to include the CallStack when it's thrown.
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"
I'd like the above example to print logs like this
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
but actually printed:
example-exe: UnknownException {caller = "willThrow"}
Also, is it a good practice to include CallStack in exceptions in Haskell?
haskell exception
haskell exception
asked Jan 2 at 0:00
Leo ZhangLeo Zhang
1,25411323
1,25411323
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Yeah I think it is good practice. If you are compiling with profiling, you can simply use
currentCallStack :: IO [String]
from GHC.Stack
. Notice that it's in IO
but I would consider it fine to unsafePerformIO
this when you throw the error if you are in pure code. Because all bottoms are equal denotationally, there's not really any violation of purity.
But if you want to get at call stacks without profiling (say you want to include it in a log message on production), you have to do more. You have to include HasCallStack
constraints everywhere you would like the stack to be reported. So
main :: IO ()
main = print f
f :: Int
f = g
g :: HasCallStack => Int
g = h
h :: HasCallStack => Int
h = error (show callStack)
Will report the call stack up to g
, but will omit f
. Sadly,
If there is no CallStack in scope and the enclosing definition has an explicit type signature, GHC will solve the HasCallStack constraint for the singleton CallStack containing just the current call-site.
That means it will omits any callers of f
, even if they do have HasCallStack
just because f
doesn't have such a constraint. I find this terribly cumbersome.
It's a fairly recent feature, so I hope the GHC team has something better in mind that they using this to move toward.
There is no other way to get a complete callstack without addingHasCallStack
everywhere? Yeah, having to add that everywhere is very cumbersome. A complete callstack would be very useful.
– Leo Zhang
Jan 2 at 15:48
Also, I found if you remove theHasCallStack
fromg
, and letf
to haveHasCallStack
, then the callstack will not includef
even iff
hasHasCallStack
.
– Leo Zhang
Jan 2 at 15:53
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53999891%2fhow-to-throw-an-exception-with-callstack%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Yeah I think it is good practice. If you are compiling with profiling, you can simply use
currentCallStack :: IO [String]
from GHC.Stack
. Notice that it's in IO
but I would consider it fine to unsafePerformIO
this when you throw the error if you are in pure code. Because all bottoms are equal denotationally, there's not really any violation of purity.
But if you want to get at call stacks without profiling (say you want to include it in a log message on production), you have to do more. You have to include HasCallStack
constraints everywhere you would like the stack to be reported. So
main :: IO ()
main = print f
f :: Int
f = g
g :: HasCallStack => Int
g = h
h :: HasCallStack => Int
h = error (show callStack)
Will report the call stack up to g
, but will omit f
. Sadly,
If there is no CallStack in scope and the enclosing definition has an explicit type signature, GHC will solve the HasCallStack constraint for the singleton CallStack containing just the current call-site.
That means it will omits any callers of f
, even if they do have HasCallStack
just because f
doesn't have such a constraint. I find this terribly cumbersome.
It's a fairly recent feature, so I hope the GHC team has something better in mind that they using this to move toward.
There is no other way to get a complete callstack without addingHasCallStack
everywhere? Yeah, having to add that everywhere is very cumbersome. A complete callstack would be very useful.
– Leo Zhang
Jan 2 at 15:48
Also, I found if you remove theHasCallStack
fromg
, and letf
to haveHasCallStack
, then the callstack will not includef
even iff
hasHasCallStack
.
– Leo Zhang
Jan 2 at 15:53
add a comment |
Yeah I think it is good practice. If you are compiling with profiling, you can simply use
currentCallStack :: IO [String]
from GHC.Stack
. Notice that it's in IO
but I would consider it fine to unsafePerformIO
this when you throw the error if you are in pure code. Because all bottoms are equal denotationally, there's not really any violation of purity.
But if you want to get at call stacks without profiling (say you want to include it in a log message on production), you have to do more. You have to include HasCallStack
constraints everywhere you would like the stack to be reported. So
main :: IO ()
main = print f
f :: Int
f = g
g :: HasCallStack => Int
g = h
h :: HasCallStack => Int
h = error (show callStack)
Will report the call stack up to g
, but will omit f
. Sadly,
If there is no CallStack in scope and the enclosing definition has an explicit type signature, GHC will solve the HasCallStack constraint for the singleton CallStack containing just the current call-site.
That means it will omits any callers of f
, even if they do have HasCallStack
just because f
doesn't have such a constraint. I find this terribly cumbersome.
It's a fairly recent feature, so I hope the GHC team has something better in mind that they using this to move toward.
There is no other way to get a complete callstack without addingHasCallStack
everywhere? Yeah, having to add that everywhere is very cumbersome. A complete callstack would be very useful.
– Leo Zhang
Jan 2 at 15:48
Also, I found if you remove theHasCallStack
fromg
, and letf
to haveHasCallStack
, then the callstack will not includef
even iff
hasHasCallStack
.
– Leo Zhang
Jan 2 at 15:53
add a comment |
Yeah I think it is good practice. If you are compiling with profiling, you can simply use
currentCallStack :: IO [String]
from GHC.Stack
. Notice that it's in IO
but I would consider it fine to unsafePerformIO
this when you throw the error if you are in pure code. Because all bottoms are equal denotationally, there's not really any violation of purity.
But if you want to get at call stacks without profiling (say you want to include it in a log message on production), you have to do more. You have to include HasCallStack
constraints everywhere you would like the stack to be reported. So
main :: IO ()
main = print f
f :: Int
f = g
g :: HasCallStack => Int
g = h
h :: HasCallStack => Int
h = error (show callStack)
Will report the call stack up to g
, but will omit f
. Sadly,
If there is no CallStack in scope and the enclosing definition has an explicit type signature, GHC will solve the HasCallStack constraint for the singleton CallStack containing just the current call-site.
That means it will omits any callers of f
, even if they do have HasCallStack
just because f
doesn't have such a constraint. I find this terribly cumbersome.
It's a fairly recent feature, so I hope the GHC team has something better in mind that they using this to move toward.
Yeah I think it is good practice. If you are compiling with profiling, you can simply use
currentCallStack :: IO [String]
from GHC.Stack
. Notice that it's in IO
but I would consider it fine to unsafePerformIO
this when you throw the error if you are in pure code. Because all bottoms are equal denotationally, there's not really any violation of purity.
But if you want to get at call stacks without profiling (say you want to include it in a log message on production), you have to do more. You have to include HasCallStack
constraints everywhere you would like the stack to be reported. So
main :: IO ()
main = print f
f :: Int
f = g
g :: HasCallStack => Int
g = h
h :: HasCallStack => Int
h = error (show callStack)
Will report the call stack up to g
, but will omit f
. Sadly,
If there is no CallStack in scope and the enclosing definition has an explicit type signature, GHC will solve the HasCallStack constraint for the singleton CallStack containing just the current call-site.
That means it will omits any callers of f
, even if they do have HasCallStack
just because f
doesn't have such a constraint. I find this terribly cumbersome.
It's a fairly recent feature, so I hope the GHC team has something better in mind that they using this to move toward.
answered Jan 2 at 0:38
luquiluqui
48.2k6114168
48.2k6114168
There is no other way to get a complete callstack without addingHasCallStack
everywhere? Yeah, having to add that everywhere is very cumbersome. A complete callstack would be very useful.
– Leo Zhang
Jan 2 at 15:48
Also, I found if you remove theHasCallStack
fromg
, and letf
to haveHasCallStack
, then the callstack will not includef
even iff
hasHasCallStack
.
– Leo Zhang
Jan 2 at 15:53
add a comment |
There is no other way to get a complete callstack without addingHasCallStack
everywhere? Yeah, having to add that everywhere is very cumbersome. A complete callstack would be very useful.
– Leo Zhang
Jan 2 at 15:48
Also, I found if you remove theHasCallStack
fromg
, and letf
to haveHasCallStack
, then the callstack will not includef
even iff
hasHasCallStack
.
– Leo Zhang
Jan 2 at 15:53
There is no other way to get a complete callstack without adding
HasCallStack
everywhere? Yeah, having to add that everywhere is very cumbersome. A complete callstack would be very useful.– Leo Zhang
Jan 2 at 15:48
There is no other way to get a complete callstack without adding
HasCallStack
everywhere? Yeah, having to add that everywhere is very cumbersome. A complete callstack would be very useful.– Leo Zhang
Jan 2 at 15:48
Also, I found if you remove the
HasCallStack
from g
, and let f
to have HasCallStack
, then the callstack will not include f
even if f
has HasCallStack
.– Leo Zhang
Jan 2 at 15:53
Also, I found if you remove the
HasCallStack
from g
, and let f
to have HasCallStack
, then the callstack will not include f
even if f
has HasCallStack
.– Leo Zhang
Jan 2 at 15:53
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53999891%2fhow-to-throw-an-exception-with-callstack%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown