Use empty cases where appropriate when deriving instances for empty types
In some sense the correct instance for
data X
deriving instance Eq X
is not (what GHC currently produces)
instance Eq X where
(==) = error "Void =="
but rather
instance Eq X where
a == b = case a of {} -- using the EmptyCase extension
See comments starting at ticket:7401#comment:101079 for justification.
The list of classes that GHC can currently derive is
- Eq, Ord, Enum, Bounded, Show, Read (Haskell 2010 Report)
- Functor, Foldable, Traversable, Typeable, Generic, Data, "any class" (
-XDerive*
)
Deriving Enum and Bounded is not currently allowed for empty data types. The showList
method of Show and the whole Read instance are easy and already implemented correctly. All the remaining methods of Haskell 2010 derivable type classes take at least one argument of the instance head type a
. I propose that all these methods be defined as an empty case on the first such argument.
Similarly in Functor, Foldable and Traversable, each method has a single argument of the form t _
where t :: * -> *
is the instance head type, and the method should be defined as an empty case on that argument.
In all these cases so far, the derived methods for a non-empty type would, at the outermost level, be a (non-empty) case on that first argument, or the equivalent (series of pattern matches, one for each constructor), so the use of an empty case is justified for an empty type.
Typeable does not care about the values or even the kind of the type at all, so it's not relevant here.
Generic and especially Data are above my pay grade, but generally I expect that methods which are normally defined by case analysis on an argument of the instance head type should be defined by an empty case, and methods that (sometimes) produce a value of the instance head type should do whatever they normally do when unable to produce such a value (like readsPrec
returning an empty list, or read
calling error
(if read
were actually a method of Read
)).
DeriveAnyClass
doesn't generate any new code, so like Typeable it's not relevant.
None of this behavior is specified by the Haskell 2010 Report, which disallows deriving any class for a type with no constructors; but see #7401 (closed). So, we are entitled to do what we think is best here.
Trac metadata
Trac field | Value |
---|---|
Version | 7.11 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |