What's the difference between throw and throwIO
The documentation says:
The throwIO variant should be used in preference to throw to raise an exception within the IO monad because it guarantees ordering with respect to other IO operations, whereas throw does not.
I'm still confused after reading it. Is there an example to show that throw will cause a problem whereas throwIO will not?
Additional question:
Is the following statement correct?
- If
throw
is being used to throw an exception in an IO, then the order of the exception is not guaranteed. - If
throw
is being used to throw an exception in a non-IO value, then the order of the exception is guaranteed.
If I need to throw an exception in a Monad Transformer, which I have to use throw
instead of throwIO
, does it guarantee the order of the exception?
haskell exception
add a comment |
The documentation says:
The throwIO variant should be used in preference to throw to raise an exception within the IO monad because it guarantees ordering with respect to other IO operations, whereas throw does not.
I'm still confused after reading it. Is there an example to show that throw will cause a problem whereas throwIO will not?
Additional question:
Is the following statement correct?
- If
throw
is being used to throw an exception in an IO, then the order of the exception is not guaranteed. - If
throw
is being used to throw an exception in a non-IO value, then the order of the exception is guaranteed.
If I need to throw an exception in a Monad Transformer, which I have to use throw
instead of throwIO
, does it guarantee the order of the exception?
haskell exception
add a comment |
The documentation says:
The throwIO variant should be used in preference to throw to raise an exception within the IO monad because it guarantees ordering with respect to other IO operations, whereas throw does not.
I'm still confused after reading it. Is there an example to show that throw will cause a problem whereas throwIO will not?
Additional question:
Is the following statement correct?
- If
throw
is being used to throw an exception in an IO, then the order of the exception is not guaranteed. - If
throw
is being used to throw an exception in a non-IO value, then the order of the exception is guaranteed.
If I need to throw an exception in a Monad Transformer, which I have to use throw
instead of throwIO
, does it guarantee the order of the exception?
haskell exception
The documentation says:
The throwIO variant should be used in preference to throw to raise an exception within the IO monad because it guarantees ordering with respect to other IO operations, whereas throw does not.
I'm still confused after reading it. Is there an example to show that throw will cause a problem whereas throwIO will not?
Additional question:
Is the following statement correct?
- If
throw
is being used to throw an exception in an IO, then the order of the exception is not guaranteed. - If
throw
is being used to throw an exception in a non-IO value, then the order of the exception is guaranteed.
If I need to throw an exception in a Monad Transformer, which I have to use throw
instead of throwIO
, does it guarantee the order of the exception?
haskell exception
haskell exception
edited Jan 1 at 23:47
Leo Zhang
asked Jan 1 at 23:23
Leo ZhangLeo Zhang
1,26211323
1,26211323
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
I think the docs could be improved. The issue you need to keep in mind with throw
and the like is that throw
returns a bottom value that "explodes" (raises an exception) when evaluated; but whether and when evaluation happens is difficult to control due to laziness.
For example:
Prelude Control.Exception> let f n = if odd n then throw Underflow else True
Prelude Control.Exception> snd (f 1, putStrLn "this is fine")
this is fine
This could arguably be what you want to happen, but usually not. e.g. rather than the tuple above you might end up with a big data structure with a single exploding element that causes an exception to be raised after your web server returns 200 to the user, or something.
throwIO
allows you to sequence raising an exception just as if it was another IO action, so it can be tightly controlled:
Prelude Control.Exception> throwIO Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow
...just like doing print 1 >> print 2
.
But note that you can actually replace throwIO
with throw
, for instance:
Prelude Control.Exception> throw Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow
Since now the exploding value is of type IO a
. It's actually not clear to me why throwIO
exists other than to document an idiom. Maybe someone else can answer that.
As a final example, this has the same issue as my first example:
Prelude Control.Exception> return (throw Underflow) >> putStrLn "this is fine"
this is fine
2
There's a bit more to it than this, too.throw
results in imprecise exceptions - GHC is allowed to rewrite code in weird ways when they're involved, because GHC is allowed to consider all bottoms to be equivalent.throwIO
prevents rewriting in that way - the exception you get will be the one thrown in the way you'd expect.
– Carl
Jan 2 at 1:23
Thanks, here's a relevant answer on that point: stackoverflow.com/questions/11070690/…
– jberryman
Jan 2 at 3:22
What is a Haskell program? A Haskell program is a pure set of equations that produces an imperative program calledmain
, and the data type for “imperative program” isIO ()
. throw, error, and undefined all cause a pure expression to fail. They don’t just mean an error has ocurred in the program; they mean there is no program. throwIO is a well-formed program that fails. It actually confuses me that many functions in the standard library, e.g.catch
, don’t make a distinction between them.
– HTNW
Jan 2 at 13:37
add a comment |
throw
is a generalization of undefined
, while throwIO
is an actual IO
action. A key difference is that many laws don't quite hold when strictness is considered (i.e., when you have undefined
(or throw
) and seq
).
> (throw Underflow :: IO ()) `seq` ()
*** Exception: arithmetic underflow
> (throw Underflow >>= pure) `seq` ()
()
Hence contradicting the law m >>= pure = m
. throwIO
doesn't have that issue, so it is the more principled way of throwing exceptions.
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%2f53999720%2fwhats-the-difference-between-throw-and-throwio%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I think the docs could be improved. The issue you need to keep in mind with throw
and the like is that throw
returns a bottom value that "explodes" (raises an exception) when evaluated; but whether and when evaluation happens is difficult to control due to laziness.
For example:
Prelude Control.Exception> let f n = if odd n then throw Underflow else True
Prelude Control.Exception> snd (f 1, putStrLn "this is fine")
this is fine
This could arguably be what you want to happen, but usually not. e.g. rather than the tuple above you might end up with a big data structure with a single exploding element that causes an exception to be raised after your web server returns 200 to the user, or something.
throwIO
allows you to sequence raising an exception just as if it was another IO action, so it can be tightly controlled:
Prelude Control.Exception> throwIO Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow
...just like doing print 1 >> print 2
.
But note that you can actually replace throwIO
with throw
, for instance:
Prelude Control.Exception> throw Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow
Since now the exploding value is of type IO a
. It's actually not clear to me why throwIO
exists other than to document an idiom. Maybe someone else can answer that.
As a final example, this has the same issue as my first example:
Prelude Control.Exception> return (throw Underflow) >> putStrLn "this is fine"
this is fine
2
There's a bit more to it than this, too.throw
results in imprecise exceptions - GHC is allowed to rewrite code in weird ways when they're involved, because GHC is allowed to consider all bottoms to be equivalent.throwIO
prevents rewriting in that way - the exception you get will be the one thrown in the way you'd expect.
– Carl
Jan 2 at 1:23
Thanks, here's a relevant answer on that point: stackoverflow.com/questions/11070690/…
– jberryman
Jan 2 at 3:22
What is a Haskell program? A Haskell program is a pure set of equations that produces an imperative program calledmain
, and the data type for “imperative program” isIO ()
. throw, error, and undefined all cause a pure expression to fail. They don’t just mean an error has ocurred in the program; they mean there is no program. throwIO is a well-formed program that fails. It actually confuses me that many functions in the standard library, e.g.catch
, don’t make a distinction between them.
– HTNW
Jan 2 at 13:37
add a comment |
I think the docs could be improved. The issue you need to keep in mind with throw
and the like is that throw
returns a bottom value that "explodes" (raises an exception) when evaluated; but whether and when evaluation happens is difficult to control due to laziness.
For example:
Prelude Control.Exception> let f n = if odd n then throw Underflow else True
Prelude Control.Exception> snd (f 1, putStrLn "this is fine")
this is fine
This could arguably be what you want to happen, but usually not. e.g. rather than the tuple above you might end up with a big data structure with a single exploding element that causes an exception to be raised after your web server returns 200 to the user, or something.
throwIO
allows you to sequence raising an exception just as if it was another IO action, so it can be tightly controlled:
Prelude Control.Exception> throwIO Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow
...just like doing print 1 >> print 2
.
But note that you can actually replace throwIO
with throw
, for instance:
Prelude Control.Exception> throw Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow
Since now the exploding value is of type IO a
. It's actually not clear to me why throwIO
exists other than to document an idiom. Maybe someone else can answer that.
As a final example, this has the same issue as my first example:
Prelude Control.Exception> return (throw Underflow) >> putStrLn "this is fine"
this is fine
2
There's a bit more to it than this, too.throw
results in imprecise exceptions - GHC is allowed to rewrite code in weird ways when they're involved, because GHC is allowed to consider all bottoms to be equivalent.throwIO
prevents rewriting in that way - the exception you get will be the one thrown in the way you'd expect.
– Carl
Jan 2 at 1:23
Thanks, here's a relevant answer on that point: stackoverflow.com/questions/11070690/…
– jberryman
Jan 2 at 3:22
What is a Haskell program? A Haskell program is a pure set of equations that produces an imperative program calledmain
, and the data type for “imperative program” isIO ()
. throw, error, and undefined all cause a pure expression to fail. They don’t just mean an error has ocurred in the program; they mean there is no program. throwIO is a well-formed program that fails. It actually confuses me that many functions in the standard library, e.g.catch
, don’t make a distinction between them.
– HTNW
Jan 2 at 13:37
add a comment |
I think the docs could be improved. The issue you need to keep in mind with throw
and the like is that throw
returns a bottom value that "explodes" (raises an exception) when evaluated; but whether and when evaluation happens is difficult to control due to laziness.
For example:
Prelude Control.Exception> let f n = if odd n then throw Underflow else True
Prelude Control.Exception> snd (f 1, putStrLn "this is fine")
this is fine
This could arguably be what you want to happen, but usually not. e.g. rather than the tuple above you might end up with a big data structure with a single exploding element that causes an exception to be raised after your web server returns 200 to the user, or something.
throwIO
allows you to sequence raising an exception just as if it was another IO action, so it can be tightly controlled:
Prelude Control.Exception> throwIO Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow
...just like doing print 1 >> print 2
.
But note that you can actually replace throwIO
with throw
, for instance:
Prelude Control.Exception> throw Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow
Since now the exploding value is of type IO a
. It's actually not clear to me why throwIO
exists other than to document an idiom. Maybe someone else can answer that.
As a final example, this has the same issue as my first example:
Prelude Control.Exception> return (throw Underflow) >> putStrLn "this is fine"
this is fine
I think the docs could be improved. The issue you need to keep in mind with throw
and the like is that throw
returns a bottom value that "explodes" (raises an exception) when evaluated; but whether and when evaluation happens is difficult to control due to laziness.
For example:
Prelude Control.Exception> let f n = if odd n then throw Underflow else True
Prelude Control.Exception> snd (f 1, putStrLn "this is fine")
this is fine
This could arguably be what you want to happen, but usually not. e.g. rather than the tuple above you might end up with a big data structure with a single exploding element that causes an exception to be raised after your web server returns 200 to the user, or something.
throwIO
allows you to sequence raising an exception just as if it was another IO action, so it can be tightly controlled:
Prelude Control.Exception> throwIO Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow
...just like doing print 1 >> print 2
.
But note that you can actually replace throwIO
with throw
, for instance:
Prelude Control.Exception> throw Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow
Since now the exploding value is of type IO a
. It's actually not clear to me why throwIO
exists other than to document an idiom. Maybe someone else can answer that.
As a final example, this has the same issue as my first example:
Prelude Control.Exception> return (throw Underflow) >> putStrLn "this is fine"
this is fine
answered Jan 2 at 0:44
jberrymanjberryman
11.8k33671
11.8k33671
2
There's a bit more to it than this, too.throw
results in imprecise exceptions - GHC is allowed to rewrite code in weird ways when they're involved, because GHC is allowed to consider all bottoms to be equivalent.throwIO
prevents rewriting in that way - the exception you get will be the one thrown in the way you'd expect.
– Carl
Jan 2 at 1:23
Thanks, here's a relevant answer on that point: stackoverflow.com/questions/11070690/…
– jberryman
Jan 2 at 3:22
What is a Haskell program? A Haskell program is a pure set of equations that produces an imperative program calledmain
, and the data type for “imperative program” isIO ()
. throw, error, and undefined all cause a pure expression to fail. They don’t just mean an error has ocurred in the program; they mean there is no program. throwIO is a well-formed program that fails. It actually confuses me that many functions in the standard library, e.g.catch
, don’t make a distinction between them.
– HTNW
Jan 2 at 13:37
add a comment |
2
There's a bit more to it than this, too.throw
results in imprecise exceptions - GHC is allowed to rewrite code in weird ways when they're involved, because GHC is allowed to consider all bottoms to be equivalent.throwIO
prevents rewriting in that way - the exception you get will be the one thrown in the way you'd expect.
– Carl
Jan 2 at 1:23
Thanks, here's a relevant answer on that point: stackoverflow.com/questions/11070690/…
– jberryman
Jan 2 at 3:22
What is a Haskell program? A Haskell program is a pure set of equations that produces an imperative program calledmain
, and the data type for “imperative program” isIO ()
. throw, error, and undefined all cause a pure expression to fail. They don’t just mean an error has ocurred in the program; they mean there is no program. throwIO is a well-formed program that fails. It actually confuses me that many functions in the standard library, e.g.catch
, don’t make a distinction between them.
– HTNW
Jan 2 at 13:37
2
2
There's a bit more to it than this, too.
throw
results in imprecise exceptions - GHC is allowed to rewrite code in weird ways when they're involved, because GHC is allowed to consider all bottoms to be equivalent. throwIO
prevents rewriting in that way - the exception you get will be the one thrown in the way you'd expect.– Carl
Jan 2 at 1:23
There's a bit more to it than this, too.
throw
results in imprecise exceptions - GHC is allowed to rewrite code in weird ways when they're involved, because GHC is allowed to consider all bottoms to be equivalent. throwIO
prevents rewriting in that way - the exception you get will be the one thrown in the way you'd expect.– Carl
Jan 2 at 1:23
Thanks, here's a relevant answer on that point: stackoverflow.com/questions/11070690/…
– jberryman
Jan 2 at 3:22
Thanks, here's a relevant answer on that point: stackoverflow.com/questions/11070690/…
– jberryman
Jan 2 at 3:22
What is a Haskell program? A Haskell program is a pure set of equations that produces an imperative program called
main
, and the data type for “imperative program” is IO ()
. throw, error, and undefined all cause a pure expression to fail. They don’t just mean an error has ocurred in the program; they mean there is no program. throwIO is a well-formed program that fails. It actually confuses me that many functions in the standard library, e.g. catch
, don’t make a distinction between them.– HTNW
Jan 2 at 13:37
What is a Haskell program? A Haskell program is a pure set of equations that produces an imperative program called
main
, and the data type for “imperative program” is IO ()
. throw, error, and undefined all cause a pure expression to fail. They don’t just mean an error has ocurred in the program; they mean there is no program. throwIO is a well-formed program that fails. It actually confuses me that many functions in the standard library, e.g. catch
, don’t make a distinction between them.– HTNW
Jan 2 at 13:37
add a comment |
throw
is a generalization of undefined
, while throwIO
is an actual IO
action. A key difference is that many laws don't quite hold when strictness is considered (i.e., when you have undefined
(or throw
) and seq
).
> (throw Underflow :: IO ()) `seq` ()
*** Exception: arithmetic underflow
> (throw Underflow >>= pure) `seq` ()
()
Hence contradicting the law m >>= pure = m
. throwIO
doesn't have that issue, so it is the more principled way of throwing exceptions.
add a comment |
throw
is a generalization of undefined
, while throwIO
is an actual IO
action. A key difference is that many laws don't quite hold when strictness is considered (i.e., when you have undefined
(or throw
) and seq
).
> (throw Underflow :: IO ()) `seq` ()
*** Exception: arithmetic underflow
> (throw Underflow >>= pure) `seq` ()
()
Hence contradicting the law m >>= pure = m
. throwIO
doesn't have that issue, so it is the more principled way of throwing exceptions.
add a comment |
throw
is a generalization of undefined
, while throwIO
is an actual IO
action. A key difference is that many laws don't quite hold when strictness is considered (i.e., when you have undefined
(or throw
) and seq
).
> (throw Underflow :: IO ()) `seq` ()
*** Exception: arithmetic underflow
> (throw Underflow >>= pure) `seq` ()
()
Hence contradicting the law m >>= pure = m
. throwIO
doesn't have that issue, so it is the more principled way of throwing exceptions.
throw
is a generalization of undefined
, while throwIO
is an actual IO
action. A key difference is that many laws don't quite hold when strictness is considered (i.e., when you have undefined
(or throw
) and seq
).
> (throw Underflow :: IO ()) `seq` ()
*** Exception: arithmetic underflow
> (throw Underflow >>= pure) `seq` ()
()
Hence contradicting the law m >>= pure = m
. throwIO
doesn't have that issue, so it is the more principled way of throwing exceptions.
answered Jan 2 at 9:42
Li-yao XiaLi-yao Xia
12.9k1429
12.9k1429
add a comment |
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%2f53999720%2fwhats-the-difference-between-throw-and-throwio%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