What's the difference between throw and throwIO












4















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?




  1. If throw is being used to throw an exception in an IO, then the order of the exception is not guaranteed.

  2. 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?










share|improve this question





























    4















    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?




    1. If throw is being used to throw an exception in an IO, then the order of the exception is not guaranteed.

    2. 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?










    share|improve this question



























      4












      4








      4








      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?




      1. If throw is being used to throw an exception in an IO, then the order of the exception is not guaranteed.

      2. 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?










      share|improve this question
















      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?




      1. If throw is being used to throw an exception in an IO, then the order of the exception is not guaranteed.

      2. 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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 1 at 23:47







      Leo Zhang

















      asked Jan 1 at 23:23









      Leo ZhangLeo Zhang

      1,26211323




      1,26211323
























          2 Answers
          2






          active

          oldest

          votes


















          4














          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





          share|improve this answer



















          • 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 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



















          1














          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.






          share|improve this answer























            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
            });


            }
            });














            draft saved

            draft discarded


















            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









            4














            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





            share|improve this answer



















            • 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 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
















            4














            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





            share|improve this answer



















            • 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 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














            4












            4








            4







            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





            share|improve this answer













            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






            share|improve this answer












            share|improve this answer



            share|improve this answer










            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 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














            • 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 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








            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













            1














            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.






            share|improve this answer




























              1














              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.






              share|improve this answer


























                1












                1








                1







                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.






                share|improve this answer













                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.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 2 at 9:42









                Li-yao XiaLi-yao Xia

                12.9k1429




                12.9k1429






























                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    Monofisismo

                    Angular Downloading a file using contenturl with Basic Authentication

                    Olmecas