Simon Hengel | 27 Nov 11:59 2012
Picon

Proposal: Add Eq instance for Control.Exception.ErrorCall

Hi,
I propose to add an Eq instance for ErrorCall.  The main motivation is
to make it more convenient to construct predicates that select specific
exceptions.

My current use case is testing for expected exceptions.  In Hspec[1] we
use predicates for that, e.g.:

  evaluate (head []) `shouldThrow` (== ErrorCall "Prelude.head: empty list")

But I think it can be useful in other situations and it is consistent
with the fact that other common exception types have an Eq instance
(e.g. ArithException, IOException, ExitCode).

Discussion period: 3 Weeks

Cheers,
Simon

[1] http://hspec.github.com/
Henning Thielemann | 27 Nov 12:12 2012
Picon

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall


On Tue, 27 Nov 2012, Simon Hengel wrote:

> I propose to add an Eq instance for ErrorCall.  The main motivation is
> to make it more convenient to construct predicates that select specific
> exceptions.
>
> My current use case is testing for expected exceptions.  In Hspec[1] we
> use predicates for that, e.g.:
>
>  evaluate (head []) `shouldThrow` (== ErrorCall "Prelude.head: empty list")

If this is an actual use case, then there is something very wrong. 
Handling non-empty lists can be done cleanly using various non-empty list 
types. Or you avoid 'head' by using 'case' or 'viewL'. If instead you plan 
to catch something then you should use Either, ExceptionalT, ErrorT or IO 
exceptions. I am afraid that an Eq instance for ErrorCall promotes the 
abuse of 'error'.
Roman Cheplyaka | 27 Nov 12:27 2012

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall

* Henning Thielemann <lemming <at> henning-thielemann.de> [2012-11-27 12:12:20+0100]
> I am afraid that an Eq instance for ErrorCall promotes the abuse of
> 'error'.

I agree.

Roman
Simon Hengel | 27 Nov 12:37 2012
Picon

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall

Henning,

> >I propose to add an Eq instance for ErrorCall.  The main motivation is
> >to make it more convenient to construct predicates that select specific
> >exceptions.
> >
> >My current use case is testing for expected exceptions.  In Hspec[1] we
> >use predicates for that, e.g.:
> >
> > evaluate (head []) `shouldThrow` (== ErrorCall "Prelude.head: empty list")
> 
> 
> If this is an actual use case, then there is something very wrong.
> Handling non-empty lists can be done cleanly using various non-empty
> list types. Or you avoid 'head' by using 'case' or 'viewL'. If
> instead you plan to catch something then you should use Either,
> ExceptionalT, ErrorT or IO exceptions. I am afraid that an Eq
> instance for ErrorCall promotes the abuse of 'error'.

Please don't get me wrong.  Personally I always prefer pattern matching
over /exception throwing functions/.  However, I still think making it
hard to "deal" with exception throw function is the wrong approach.

Regarding testing: Failure behavior is part of the public interface of a
function.  If a function throws an exception (whether I like it or not),
I'd like to have it documented.  The best way to document something is a
test case (IMHO).

Cheers,
Simon
(Continue reading)

Henning Thielemann | 27 Nov 12:57 2012
Picon

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall


On Tue, 27 Nov 2012, Simon Hengel wrote:

>> If this is an actual use case, then there is something very wrong.
>> Handling non-empty lists can be done cleanly using various non-empty
>> list types. Or you avoid 'head' by using 'case' or 'viewL'. If
>> instead you plan to catch something then you should use Either,
>> ExceptionalT, ErrorT or IO exceptions. I am afraid that an Eq
>> instance for ErrorCall promotes the abuse of 'error'.
>
> Please don't get me wrong.  Personally I always prefer pattern matching
> over /exception throwing functions/.  However, I still think making it
> hard to "deal" with exception throw function is the wrong approach.

If you use the exception techniques that I enumerated it is easy to handle 
those exceptions.

> Regarding testing: Failure behavior is part of the public interface of a
> function.  If a function throws an exception (whether I like it or not),
> I'd like to have it documented.  The best way to document something is a
> test case (IMHO).

In my opinion the better way is to document it in the type. This is what 
the Error like monads are about.
Roman Cheplyaka | 27 Nov 13:48 2012

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall

* Simon Hengel <sol <at> typeful.net> [2012-11-27 12:37:44+0100]
> Please don't get me wrong.  Personally I always prefer pattern matching
> over /exception throwing functions/.  However, I still think making it
> hard to "deal" with exception throw function is the wrong approach.
> 
> Regarding testing: Failure behavior is part of the public interface of a
> function.  If a function throws an exception (whether I like it or not),
> I'd like to have it documented.  The best way to document something is a
> test case (IMHO).

Isn't the person who writes tests usually the same as the person who
writes the code which is being tested? So, if writing tests for
ErrorCall is inconvenient, that would (hopefully) encourage people to
write their own, meaningful, exceptions.

Roman
Michael Snoyman | 27 Nov 12:44 2012

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall




On Tue, Nov 27, 2012 at 1:12 PM, Henning Thielemann <lemming <at> henning-thielemann.de> wrote:

On Tue, 27 Nov 2012, Simon Hengel wrote:

I propose to add an Eq instance for ErrorCall.  The main motivation is
to make it more convenient to construct predicates that select specific
exceptions.

My current use case is testing for expected exceptions.  In Hspec[1] we
use predicates for that, e.g.:

 evaluate (head []) `shouldThrow` (== ErrorCall "Prelude.head: empty list")


If this is an actual use case, then there is something very wrong. Handling non-empty lists can be done cleanly using various non-empty list types. Or you avoid 'head' by using 'case' or 'viewL'. If instead you plan to catch something then you should use Either, ExceptionalT, ErrorT or IO exceptions. I am afraid that an Eq instance for ErrorCall promotes the abuse of 'error'.


+1 on the proposal. Even if I'm opposed to partial functions, I'm in favor of making it easier to test them reliably.

Michael 
_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Henning Thielemann | 27 Nov 12:59 2012
Picon

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall


On Tue, 27 Nov 2012, Michael Snoyman wrote:

> +1 on the proposal. Even if I'm opposed to partial functions, I'm in 
> favor of making it easier to test them reliably.

How can you be sure that you get a certain error? Depending on the order 
of evaluation you might get different error messages if there are multiple 
possible ways to fail. I think automated testing against specific error 
messages will not work reliably.
Michael Snoyman | 27 Nov 13:09 2012

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall




On Tue, Nov 27, 2012 at 1:59 PM, Henning Thielemann <lemming <at> henning-thielemann.de> wrote:

On Tue, 27 Nov 2012, Michael Snoyman wrote:

+1 on the proposal. Even if I'm opposed to partial functions, I'm in favor of making it easier to test them reliably.

How can you be sure that you get a certain error? Depending on the order of evaluation you might get different error messages if there are multiple possible ways to fail. I think automated testing against specific error messages will not work reliably.

Sure, in some cases that's true. The idea would be to structure the test case in such a way that we no with certainty which way it will fail. Simon's initial example will always fail in the same way.

Michael 
_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Henning Thielemann | 27 Nov 13:22 2012
Picon

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall


On Tue, 27 Nov 2012, Michael Snoyman wrote:

> Sure, in some cases that's true. The idea would be to structure the test case in such a way that we no with
> certainty which way it will fail. Simon's initial example will always fail in the same way.

The message for head of empty list may be changed without warning ...
Michael Snoyman | 27 Nov 13:25 2012

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall




On Tue, Nov 27, 2012 at 2:22 PM, Henning Thielemann <lemming <at> henning-thielemann.de> wrote:

On Tue, 27 Nov 2012, Michael Snoyman wrote:

Sure, in some cases that's true. The idea would be to structure the test case in such a way that we no with
certainty which way it will fail. Simon's initial example will always fail in the same way.

The message for head of empty list may be changed without warning ...

That argument can be applied to any form of automated testing.

doSomething :: Int -> Int

doSomething 5 `shouldBe` 6

If the behavior of doSomething suddenly changes, then your test will fail. In fact, that's one of the *advantages* of having a test suite: it catches these kinds of unexpected changes.

Michael
_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Simon Hengel | 27 Nov 13:22 2012
Picon

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall

> How can you be sure that you get a certain error? Depending on the
> order of evaluation you might get different error messages if there
> are multiple possible ways to fail. I think automated testing
> against specific error messages will not work reliably.

If the function/value under specification is so "insane" that it
contains a /set of exceptions/, then you have to be prepared to get any
of those [1]:

  evaluate value
    `shouldThrow` (||) <$> (== ErrorCall "foo") <*> (== ErrorCall "bar")

Again, I'm not implying that it's a good idea to write a function that
behave like that.  But if you do, I'd at least like to have it
documented ;)

Cheers,
Simon

[1] http://research.microsoft.com/en-us/um/people/simonpj/papers/imprecise-exn.htm
Henning Thielemann | 27 Nov 14:07 2012
Picon

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall


On Tue, 27 Nov 2012, Simon Hengel wrote:

> If the function/value under specification is so "insane" that it
> contains a /set of exceptions/, then you have to be prepared to get any
> of those [1]:
>
>  evaluate value
>    `shouldThrow` (||) <$> (== ErrorCall "foo") <*> (== ErrorCall "bar")
>
> Again, I'm not implying that it's a good idea to write a function that
> behave like that.  But if you do, I'd at least like to have it
> documented ;)

My advice to programmers is: If you are starting to document insane 
behavior, wait a minute and think about how to avoid it. In many cases 
this helps. :-) Having said that you might assist the users of hspec by 
providing variants of shouldThrow, say shouldCallError, that matches error 
messages. Additionally I would add a DEPRECATE pragma to shouldCallError 
with a message that tells the programmer that he should think twice.
Simon Marlow | 27 Nov 14:57 2012
Picon

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall

On 27/11/12 10:59, Simon Hengel wrote:
> Hi,
> I propose to add an Eq instance for ErrorCall.  The main motivation is
> to make it more convenient to construct predicates that select specific
> exceptions.
>
> My current use case is testing for expected exceptions.  In Hspec[1] we
> use predicates for that, e.g.:
>
>    evaluate (head []) `shouldThrow` (== ErrorCall "Prelude.head: empty list")
>
> But I think it can be useful in other situations and it is consistent
> with the fact that other common exception types have an Eq instance
> (e.g. ArithException, IOException, ExitCode).
>
> Discussion period: 3 Weeks

Already did it, a few weeks ago:

http://www.haskell.org/pipermail/cvs-libraries/2012-October/016043.html

Cheers,
	Simon
Edward Kmett | 27 Nov 16:30 2012
Picon

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall

There are a number of other data types in that module that have a similar construction IIRC, such as AssertionFailed, NoMethodError, PatternMatchFail, RecConError, RelSelError, etc. which should probably pick up Eq, Ord for consistency (and become newtypes). 


and a few others that can have the obvious trivial, empty Eq, Ord like NonTermination, NestedAtomically, BlockedIndefinitelyOnMVar.

The module is currently a bit ad hoc about which types support Eq and Ord. For instance, ArrayException already supported this kind of Eq/Ord, and all the multiple constructor versions did, but none of the single-constructor trivial versions and only some of the reasonable-to-newtype ones.

-Edward

On Tue, Nov 27, 2012 at 8:57 AM, Simon Marlow <marlowsd <at> gmail.com> wrote:
On 27/11/12 10:59, Simon Hengel wrote:
Hi,
I propose to add an Eq instance for ErrorCall.  The main motivation is
to make it more convenient to construct predicates that select specific
exceptions.

My current use case is testing for expected exceptions.  In Hspec[1] we
use predicates for that, e.g.:

   evaluate (head []) `shouldThrow` (== ErrorCall "Prelude.head: empty list")

But I think it can be useful in other situations and it is consistent
with the fact that other common exception types have an Eq instance
(e.g. ArithException, IOException, ExitCode).

Discussion period: 3 Weeks

Already did it, a few weeks ago:

http://www.haskell.org/pipermail/cvs-libraries/2012-October/016043.html


Cheers,
        Simon



_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Simon Hengel | 28 Nov 14:09 2012
Picon

Re: Proposal: Add Eq instance for Control.Exception.ErrorCall

On Tue, Nov 27, 2012 at 01:57:11PM +0000, Simon Marlow wrote:
> On 27/11/12 10:59, Simon Hengel wrote:
> >Hi,
> >I propose to add an Eq instance for ErrorCall.  The main motivation is
> >to make it more convenient to construct predicates that select specific
> >exceptions.
> >
> >My current use case is testing for expected exceptions.  In Hspec[1] we
> >use predicates for that, e.g.:
> >
> >   evaluate (head []) `shouldThrow` (== ErrorCall "Prelude.head: empty list")
> >
> >But I think it can be useful in other situations and it is consistent
> >with the fact that other common exception types have an Eq instance
> >(e.g. ArithException, IOException, ExitCode).
> >
> >Discussion period: 3 Weeks
> 
> Already did it, a few weeks ago:
> 
> http://www.haskell.org/pipermail/cvs-libraries/2012-October/016043.html

Thanks :)

Gmane