
Hello, Some functions in Data.Ratio call the error function. The following is an example: recip (0:%_) = error "Ratio.%: zero denominator" We cannot catch this error as ArithException since it is ErrorCall. Are there any reasons to not use ArithException? --Kazu

On Tue, 5 Jun 2012, Kazu Yamamoto (山本和彦) wrote:
Some functions in Data.Ratio call the error function. The following is an example:
recip (0:%_) = error "Ratio.%: zero denominator"
We cannot catch this error as ArithException since it is ErrorCall. Are there any reasons to not use ArithException?
It is intended that you do not divide by zero, also because it is so simple to check it before calling the function. The best solution would certainly be a number type that excludes zero values, such that division by zero can be catched at compile time. But currently Haskell's type system may not be expressive enough to handle this without a lot of explicit type conversion.

Hello Henning, Thank you for reply.
It is intended that you do not divide by zero, also because it is so simple to check it before calling the function.
I'm not convinced. For instance, for division by zero of Int, it is also easy to check it before calling the "div" function. But we have DivideByZero.
The best solution would certainly be a number type that excludes zero values, such that division by zero can be catched at compile time. But currently Haskell's type system may not be expressive enough to handle this without a lot of explicit type conversion.
I'm not suggesting such a drastic change. What I want to suggest is to define a new data constructor for ArithException and to change % so that it throws the new data constructor. In test code, we want to check the exception of Data.Ratio with hspec-shouldbe as follows: evaluate (1 `div'` 0) `shouldThrow` anyArithException --Kazu

On Tue, 5 Jun 2012, Kazu Yamamoto (山本和彦) wrote:
Hello Henning,
Thank you for reply.
It is intended that you do not divide by zero, also because it is so simple to check it before calling the function.
I'm not convinced. For instance, for division by zero of Int, it is also easy to check it before calling the "div" function. But we have DivideByZero.
I know people get annoyed quickly if I start a new round of "errors vs. exceptions" ... In Haskell there is only one undefined value and that should be equivalent to an infinite loop. Every distinction between 'error', 'undefined', infinite loop, DivideByZero is only for debugging purposes. Don't rely on being able to catch them! The only correct way to cope with division by zero is to not let it happen.

Then why don't we change it to ArithException for debugging purposes? =) Cheers, -- Felipe – enviado do meu Galaxy Tab.

Hello Henning,
I know people get annoyed quickly if I start a new round of "errors vs. exceptions" ...
Would you explain how they get annoyed concretely?
In Haskell there is only one undefined value and that should be equivalent to an infinite loop. Every distinction between 'error', 'undefined', infinite loop, DivideByZero is only for debugging purposes. Don't rely on being able to catch them! The only correct way to cope with division by zero is to not let it happen.
Let's define a new constructor of ArithException for debugging purposes. --Kazu

On 5 June 2012 17:24, Henning Thielemann
On Tue, 5 Jun 2012, Kazu Yamamoto (山本和彦) wrote:
Some functions in Data.Ratio call the error function. The following is an example:
recip (0:%_) = error "Ratio.%: zero denominator"
We cannot catch this error as ArithException since it is ErrorCall. Are there any reasons to not use ArithException?
It is intended that you do not divide by zero, also because it is so simple to check it before calling the function.
Surely if that expectation (that the user not divide by zero) was actually part of the design intention, then the check within the function itself would be redundant. There is already a check within the function. Perhaps changing its behaviour to use the existing ArithException DivideByZero would be consistent with other types? +1 to Kazu's suggestion to throw DivideByZero. For the implementation, if the underlying type throws DivideByZero on division by zero anyway, perhaps all that is requried is to remove the check.
The best solution would certainly be a number type that excludes zero values, such that division by zero can be catched at compile time. But currently Haskell's type system may not be expressive enough to handle this without a lot of explicit type conversion.
Indeed, it'd be fun to implement this properly in a different language. For now let's narrow our options down to things that work in Haskell. Conrad.

I have to admit I rather prefer the notion of throwing a DivideByZero in
this case as well, especially since a lot of things that would otherwise by
Double/Float round trip through Rational temporarily during conversion.
-Edward
On Tue, Jun 5, 2012 at 9:35 PM, Conrad Parker
On 5 June 2012 17:24, Henning Thielemann
wrote: On Tue, 5 Jun 2012, Kazu Yamamoto (山本和彦) wrote:
Some functions in Data.Ratio call the error function. The following is an example:
recip (0:%_) = error "Ratio.%: zero denominator"
We cannot catch this error as ArithException since it is ErrorCall. Are there any reasons to not use ArithException?
It is intended that you do not divide by zero, also because it is so
simple
to check it before calling the function.
Surely if that expectation (that the user not divide by zero) was actually part of the design intention, then the check within the function itself would be redundant.
There is already a check within the function. Perhaps changing its behaviour to use the existing ArithException DivideByZero would be consistent with other types?
+1 to Kazu's suggestion to throw DivideByZero.
For the implementation, if the underlying type throws DivideByZero on division by zero anyway, perhaps all that is requried is to remove the check.
The best solution would certainly be a number type that excludes zero values, such that division by zero can be catched at compile time. But currently Haskell's type system may not be expressive enough to handle this without a lot of explicit type conversion.
Indeed, it'd be fun to implement this properly in a different language. For now let's narrow our options down to things that work in Haskell.
Conrad.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On 6/5/12 9:35 PM, Conrad Parker wrote:
+1 to Kazu's suggestion to throw DivideByZero.
Another +1 from me. The essential nature of the function wouldn't be altered any, it'd just give a more precise error. Seems like an improvement regardless of how one feels about errors/exceptions/bottoms. Also, I think using DivideByZero is appropriate here. No need to invent a new exception type. -- Live well, ~wren

Hello,
The essential nature of the function wouldn't be altered any, it'd just give a more precise error. Seems like an improvement regardless of how one feels about errors/exceptions/bottoms.
Also, I think using DivideByZero is appropriate here. No need to invent a new exception type.
GHC.Real uses the error function in some places. I believe that most cases should be throw ArithException. I will survey and make a comprehensive proposal. If there are other modules to be surveyed, please let me know. --Kazu

On 06/06/2012 06:11, Kazu Yamamoto (山本和彦) wrote:
Hello,
The essential nature of the function wouldn't be altered any, it'd just give a more precise error. Seems like an improvement regardless of how one feels about errors/exceptions/bottoms.
Also, I think using DivideByZero is appropriate here. No need to invent a new exception type.
GHC.Real uses the error function in some places. I believe that most cases should be throw ArithException. I will survey and make a comprehensive proposal.
If there are other modules to be surveyed, please let me know.
I'll go ahead and make this change. Thanks for the suggestion! Cheers, Simon

I'll go ahead and make this change. Thanks for the suggestion!
I agree that ArithException feels more appropriate here. But I make two observations: (1) It replaces specific error messages with less specific ones. The error message will not include the function/operator name anymore, e.g.: ghci> 1 % 0 *** Exception: Ratio.%: zero denominator would become: ghci> 1 % 0 *** Exception: divide by zero (2) It is a breaking API change, and the complier won't help you to detect it in client code. I'm not saying that this is a bad idea, I just try to understand what the benefits of this breaking change are. If it only gives us less useful error messages, than I'm not convinced**. Cheers, Simon ** If we had stack traces with source locations that are enabled by default, I would be less reluctant to this change.

On 6/13/12 6:57 AM, Simon Hengel wrote:
I'll go ahead and make this change. Thanks for the suggestion!
I agree that ArithException feels more appropriate here. But I make two observations:
(1) It replaces specific error messages with less specific ones.
The error message will not include the function/operator name anymore, e.g.:
ghci> 1 % 0 *** Exception: Ratio.%: zero denominator
would become:
ghci> 1 % 0 *** Exception: divide by zero
That's no good. I wonder whether ArithExceptions should be given their code location a la assertion failures[1]. Probably all the built-in exception types should do so. [1] http://www.haskell.org/ghc/docs/7.4.1/html/users_guide/assertions.html -- Live well, ~wren

On 14/06/2012 02:27, wren ng thornton wrote:
On 6/13/12 6:57 AM, Simon Hengel wrote:
I'll go ahead and make this change. Thanks for the suggestion!
I agree that ArithException feels more appropriate here. But I make two observations:
(1) It replaces specific error messages with less specific ones.
The error message will not include the function/operator name anymore, e.g.:
ghci> 1 % 0 *** Exception: Ratio.%: zero denominator
would become:
ghci> 1 % 0 *** Exception: divide by zero
That's no good. I wonder whether ArithExceptions should be given their code location a la assertion failures[1]. Probably all the built-in exception types should do so.
[1] http://www.haskell.org/ghc/docs/7.4.1/html/users_guide/assertions.html
But that wouldn't help - you'd just get a code location somewhere deep in the base package every time. So we could make a separate RatioZeroDenominator exception, and add that to ArithException. That would mean no loss of information relative to the current state of affairs. Cheers, Simon

On 6/14/12 6:32 AM, Simon Marlow wrote:
On 14/06/2012 02:27, wren ng thornton wrote:
That's no good. I wonder whether ArithExceptions should be given their code location a la assertion failures[1]. Probably all the built-in exception types should do so.
But that wouldn't help - you'd just get a code location somewhere deep in the base package every time.
Shouldn't it give the location of the use site of (%)? No, I suppose that'd require more special magic... -- Live well, ~wren
participants (8)
-
Conrad Parker
-
Edward Kmett
-
Felipe Almeida Lessa
-
Henning Thielemann
-
Kazu Yamamoto
-
Simon Hengel
-
Simon Marlow
-
wren ng thornton