I'm not sure if this has been discussed before...
Suppose you have an implementation of a queue ADT (exporting the type
constructor Queue) and an implementation of a set ADT (exporting the
type constructor Set, and requiring an ordering of elements). Suppose
now that you want to form a set of queues of integers:
Set (Queue Int).
There is a problem here: You must specify how to order the elements of
type (Queue Int). Normally, given you can order the type (a), you can
simply derive the ordering of (Queue a) (assuming the definition of
Queue met certain criteria). However, changing:
data Queue a = ...
to
data Ord a => Queue a = ... deriving (Eq,Ord)
forbids you from forming queues of unorderable elements elsewhere,
which clearly violates the purpose of a queue ADT.
Instead, one must place explicit instances inside the queue
implementation:
instance Eq a => Eq (Queue a) where ...
instance Ord a => Ord (Queue a) where ...
using (==) and compare on elements of type (a) and hand-deriving the
definitions on type (Queue a).
It would be better if something like:
instance deriving Eq a => Eq (Queue a)
instance deriving Ord a => Ord (Queue a)
was allowed, which derived the methods _if possible_ but otherwise
does not restrict the use of the types.
It is also questionable if every implementation should provide every
derivation of every default class, "just in case", but that is another
issue... (though one could argue that the instance cannot be provided
outside of the implementation as the instance requires knowledge of
the definition of the type constructor, which is hidden within an
implementation of an ADT).
Cheers,
Graeme.