Show, Eq not necessary for Num [Was: Revamping the numeric classes]
Wed, 07 Feb 2001 15:47:17 +0000
Patrik Jansson wrote:
> [I am not sure a more mathematically correct numeric class system is
> suitable for inclusion in the language specification of Haskell (a
> library would certainly be useful though)....]
I think it should be done at the language level.
Previously Brian Boutel wrote:
> Haskell was intended for use by programmers who may not be
> mathematicians, as a general purpose language. Changes to make keep
> mathematicians happy tend to make it less understandable and attractive
> to everyone else.
> * most usage of (+), (-), (*) is on numbers which support all of them.
> * Haskell equality is a defined operation, not a primitive, and may not
> be decidable. It does not always define equivalence classes, because
> a==a may be Bottom, so what's the problem? It would be a problem,
> though, to have to explain to a beginner why they can't print the result
> of a computation.
Some people here might recall that I cried loudly and in despair (OK,
I am exaggerating a bit...) about the inadequacy of the Num hierarchy
much before Sergey Mechveliani's proposal. Finally I implemented my
own home-brewed hierarchy of Rings, AdditiveGroups, Modules, etc. in
order to play with differential structures and graphical objects.
And arithmetic on functions.
I AM NOT A MATHEMATICIAN, and still, I see very strongly the need for
a sane math layer in Haskell on behalf of 'general purpose' programming.
Trying to explain to comp. sci students (who, at least here, don't like
formal mathematics too much...) WHY the Haskell Num hierarchy is as
it is, is simply hopeless, because some historical accidents were never
* I don't care about "most usage of (+), (-), (*) is on numbers which
support all of them" if this produces a chaos if you want to use
Haskell for geometry, or graphics, needing vectors.
From this point of view a slightly simpler (in this context) type system
of Clean seems to be better. And I appreciate also the possibility to
define arithmetic operations on *functions*, which is impossible in
Haskell because of this Eq/Show superclass constraints.
> In the uncoupled case the users have the choice to define Eq and Show
> instances that make sense to them. A library designer could provide the Eq
> and Show instances in two separate modules to give the users maximum
> /Patrik Jansson
I don't want to be too acrimonious nor sarcastic, but those people who
claim that Haskell as a "universal" language should not follow too
closely a decent mathematical discipline, serve the devil. When math
is taught at school at the elementary level, with full knowledge of the
fact that almost nobody will follow the mathematical career afterwards,
the rational, logical side of all constructions is methodologically
essential. 10 years old pupils learn that you can add two dollars to
7 dollars, but multiplying dollars has not too much sense (a priori),
and adding dollars to watermelons is dubious. Numbers are delicate
abstractions, and treating them in a cavalière manner in a supposedly
"universal" language, harms not only mathematicians. As you see,
(*) together with (+) is silly not only to vector spaces, but also
for dimensional quantities, useful outside math (if only for debugging).
"Ch. A. Herrmann" wrote:
> the problem is that the --majority, I suppose?-- of mathematicians
> tend to overload operators. They use "*" for matrix-matrix
> multiplication as well as for matrix-vector multiplication etc.
> Therefore, a quick solution that implements groups, monoids, Abelian
> groups, rings, Euclidean rings, fields, etc. will not be sufficient.
> I don't think that it is acceptable for a language like Haskell
> to permit the user to overload predefined operators, like "*".
Wha do you mean "predefined" operators? Predefined where? Forbid what?
Using the standard notation even to multiply rationals or complexes?
And leave this possibility open to C++ programmers who can overload
anything without respecting mathematical congruity?
A serious mathematician who sees the signature (*) :: a -> a -> a
won't try to use it for multiplying a matrix by a vector. But using
it as a basic operator within a monoid is perfectly respectable.
No need to "lift" or "promote" scalars into vectors/matrices, etc.
For "scaling" I use personally an operation (*>) defined within
the Module constructor class, but I am unhappy, because
(*>) :: a -> (t a) -> (t a) declared in a Module instance of
the constructor t prevents from using it in the case where
(t a) in reality is a. (By default (*>) maps (x*) through the
elements of (t ...), and kinds "*" are not constructors...