
On Sat, 9 Sep 2006, Jón Fairbairn wrote:
Aaron Denney
writes: On 2006-09-08, Jón Fairbairn
wrote: Why shouldn't Naturals be more primitive than Integers?
Certainly they're more primitive. Too primitive to have reasonable algebraic properties.
Hmph. Naturals obey (a+b)+c == a+(b+c), which is a nice and reasonable algebraic property that Float and Double don't obey. In fact Float and Double have lots of /un/reasonable algebraic properties, but we still have them in the language. (I think they should be turfed out into a numerical library).
Since floats are so different, maybe we should provide a different type hierarchy for them. Say class Additive a where (+) :: a -> a -> a ... class Additive a => Ring a where (*) :: a -> a -> a ... class ApproximateRing a where (+~) :: a -> a -> a (*~) :: a -> a -> a ... instance ApproximateRing Float instance ApproximateRing Rational instance Ring Rational Approximating numeric class instances do not satisfy the algebraically interesting laws, whereas instances of exact numeric class satisfy them. That is, floating point and fixed point numbers can only be instances of Approximate* classes and exact representations of mathematical objects like integers, rationals, complex numbers, polynomials can be instances of both exact and approximating numeric classes. However, e.g. the integers as presented in the computer still constitute no ring, because the domain is not closed. E.g. a power with sufficient high exponent lets any Haskell program run out of memory. Having different type hierarchies for approximating and exact numbers may be inconvenient at the first glance, because you have to implement say polynomial and matrix multiplication for both kinds of type classes, but they can share code and they can adapt to subtle differences. E.g. a fast determinant algorithm for a matrix over rings is totally different from a fast and numerically stable determinant computation of float matrices.