Show, Eq not necessary for Num [Was: Revamping the numeric c
Thu, 08 Feb 2001 15:11:21 +0100 (CET)
On 07-Feb-2001 Patrik Jansson wrote:
(interesting stuff deleted)
> As far as I remember from the earlier discussion, the only really visible
> reason for Show, Eq to be superclasses of Num is that class contexts are
> simpler when (as is often the case) numeric operations, equality and show
> are used in some context.
> f :: Num a => a -> String -- currently
> f a = show (a+a==2*a)
> If Show, Eq, Num were uncoupled this would be
> f :: (Show a, Eq a, Num a) => a -> String
> But I think I could live with that. (In fact, I rather like it.)
Basically I'm too.
However, what is missing for me is something like:
type Comfortable a = (Show a, Eq a, Num a) => a
class (Show a, Read a, Eq a) => Comfortable a
instance (Show a, Read a, Eq a) => Comfortable a
I think here is a point where a general flaw of class hierachies as a mean
of software design becomes obvious, which consists of forcing the programmer
to arbitrarily prefer few generalizations to all others in a global,
context-independent design decision.
The oo community (being the source of all the evil...) usually relies on the
rather problematic ontological assumption that, at least from a certain point
of view (problem domain, design, implemention), the relevant concepts form in
a natural way a kind a generalization hierarchy, and that this generalization
provides a natural way to design the software (in our case, determine the
type system in some a-priory fashion).
Considering the fact that a concept, for which (given a certain point of view)
n elementary predicates hold a-priory, n! possible generalizations exist
a-priory, this assumption can be questioned.
In contrary to the given assumption, I have made the experience that, when
trying to classify concepts, even a light shift in the situation being
under consideration can lead to a severe change in what appears to be the
Besides this, as is apparent in Show a => Num a, it is not always a priory
generalizations that are really needed. Instead, the things must be fit
into the current point of view with a bit force, thus changing
concepts or even inventing new ones.
(For example, in the oo community, which likes (or is forced?) to "ontologize"
relationships into "objects", has invented "factories" for different things,
ranging from GUI border frames to database connection handles.
Behind such an at first glance totally arbitary conceptualization might stand
a more rational concept, for example applying a certain library design principle
called "factory" to different types of things. However one can't always wait
until the rationale behind a certain solution is clearly recognized.)
In my experience, both class membership and generalization relationships are
often needed locally and post hoc, and they sometimes even express empirical
(a-posteriory) relations between concepts instead of true analytical (a-priory)
As a consequence, for my opinion, programming languages should make it
possible and easy to employ post-hoc and local class membership declarations and
post-hoc and local class hierarchy declarations (or even re-organizations).
There will of course be situations where a global a-priory declaration of
generalization nevertheless still make completely sense.
For Haskell, I could imagine (without having having much thought about) in
addition to the things mentioned in the beginning, several things making
supporting the "locally, fast and easy", including a mean to define classes
with implied memberships, for example declarations saying that "Foo is the class
of all types in scope for which somefoo :: ... is defined", or declarations
saying that "class Num is locally restricted to all instances of global Num
which also belong to Eq".
Skalitzer Str. 79
10997 Berlin (Germany)
fon: +49 (030) 612 852 16
for pgp public key see: