Discussion: adding displayException to Exception class

Michael Sloan mgsloan at gmail.com
Wed Oct 29 13:42:10 UTC 2014


I strongly agree with this proposal.  It's nice to encode in the API
that these error messages are expected to be displayed to users of
applications, and not just developers.  A particularly blatant example
of this going wrong is in System.IO.Error, where you get this
delightful behavior:

> fail "brain exploded"
*** Exception: user error (brain exploded)

The poor user is going to think that the program is accusing them of
having an exploded brain.  Similarly:

Prelude> Just x <- return Nothing
*** Exception: user error (Pattern match failure in do expression at
<interactive>:5:1-6)

This is clearly a programming error, not a "user error".

In order to encourage thought about application user consumption of
error messages, I think a couple warnings ought to be added:

1) A warning when the definition of "displayException" is omitted.
This would be a new GHC warning pragma, which could potentially re-use
the syntax from MINIMAL, to make the warning more flexible.  It would
recommend that they write a custom implementation and consider how the
error will look to application users (though, not at the cost of
informativeness to developers).  It could also warn about the pending
removal of the Show superclass and default implementation of
"displayException", if that was decided on (I think it should be!)

2) A warning for all uses of "show :: a -> String" when in a context
where "Exception a" holds.  This would also be a new variety of
warning, potentially hardcoded in GHC, but ideally generalized.  It's
important to have this warning because users might still be using
'show' when 'displayException' is more appropriate.  How to suppress
such warnings when you really do want 'show'?  A "showException =
show" function would work for that.

A warning when "Show a" is used when in a context where "Exception a"
holds would catch additional cases.  However, it would be much more
spammy and unclear how to suppress it.  I think the warning describe
above is still worth it, though, even if it's just to catch situations
where 'show' is being used on a nested exception value in order to
implement the 'displayException' method (or the instance of Show that
relies on).

This would also ease the pain of removing Show as a superclass
constraint.  I imagine this removal would break more code than the
removal of Eq / Show as superclasses of Num.

Michael

On Tue, Oct 28, 2014 at 4:43 PM, Michael Snoyman <michael at snoyman.com> wrote:
> I don't want to make a format proposal yet, just open up discussion on an
> issue, and see how others feel about it.
>
> As I recently commented on this list[1], the Show typeclass is overloaded
> with multiple meanings (serialization, debug info, and user-friendly data
> display). The general consensus seems to be that the official semantics for
> Show should be for serialization (as paired up with Read).
>
> However, there's at least one use case in base which explicitly uses Show
> for non-serialization purposes: the Exception class. All instances of
> Exception are required to have an instance of Show, but there's no way to
> actually serialize exceptions generally[2]. So by construction and by
> practice, the Show instance for Exception is used exclusively for the latter
> two categories I mentioned (debug info and user-friendly data display).
>
> As a result of that, it's quite common[3] to define a Show instance for
> exception types that is *not* serializable, but rather user friendly. This
> however seems to contradict what is accepted as good practice in general.
>
>
> I have a possible solution that I'd like to propose as a strawman: add a new
> method to the Exception typeclass:
>
>     displayException :: e -> String
>     displayException = show
>
> The name is up for debate, but I chose `display` since it seems to already
> be used elsewhere for user-friendly output. Other possible choices are
> showException or prettyException. The default implementation will reuse the
> Show instance, so no user code will be broken by this[4].
>
> In the short term, the only other change I'd recommend is that the default
> exception handler use `displayException` instead of `show` for printing
> uncaught exceptions. Longer term, after deprecation cycles, we could
> consider removing the Show superclass from Exception.
>
> Again, this isn't a real proposal (yet), I'm more interested now in what
> people think about such a change.
>
> Michael
>
> [1] http://www.haskell.org/pipermail/libraries/2014-October/023957.html
> [2] Both due to how extensible exceptions work, and due to the lack of a
> Read superclass.
> [3] This discussion started when Chris Done and I were working with the tar
> package, which defines custom renderings for FormatError. I've implemented
> this same technique in some of my libraries, and I'm sure there are many
> other examples on Hackage.
> [4] Barring the standard issue of new identifiers clashing with identifiers
> defined locally.
>
> _______________________________________________
> Libraries mailing list
> Libraries at haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
>


More information about the Libraries mailing list