Revamping the numeric classes
Tom Pledger
Tom.Pledger@peace.com
Thu, 8 Feb 2001 21:00:58 +1300 (NZDT)
Dylan Thurston writes:
:
 (A question in the above context is whether the literal '0' should
 be interpreted as 'fromInteger (0::Integer)' or as 'zero'.
 Opinions?)
Opinions? Be careful what you wish for. ;)
In a similar discussion last year, I was making wistful noises about
subtyping, and one of Marcin's questions
http://www.mailarchive.com/haskellcafe@haskell.org/msg00125.html
was whether the numeric literal 10 should have type Int8 (2's
complement octet) or Word8 (unsigned octet). At the time I couldn't
give a wholly satisfactory answer. Since then I've read the oftcited
paper "On Understanding Types, Data Abstraction, and Polymorphism"
(Cardelli & Wegner, ACM Computing Surveys, Dec 1985), which suggests a
nice answer: give the numeric literal 10 the range type 10..10, which
is defined implicitly and is a subtype of both 128..127 (Int8) and
0..255 (Word8).
The differences in arithmetic on certain important range types could
be represented by multiple primitive functions (or perhaps foreign
functions, through the FFI):
primAdd :: Integer > Integer > Integer  arbitrary precision
primAdd8s :: Int8 > Int8 > Int8  overflow at 129, 128
primAdd8u :: Word8 > Word8 > Word8  overflow at 1, 256
 etc.
instance Additive Integer where
zero = 0
(+) = primAdd
...with similar instances for the integer subrange types which may
overflow. These other instances would belong outside the standard
Prelude, so that the ambiguity questions don't trouble people (such as
beginners) who don't care about the space and time advantages of fixed
precision integers.
Subtyping offers an alternative approach to handling arithmetic
overflows:
 Use only arbitrary precision arithmetic.
 When calculated result *really* needs to be packed into a fixed
precision format, project it (or treat it down, etc., whatever's
your preferred name), so that overflows are represented as
Nothing.
For references to other uses of class Subtype see:
http://www.mailarchive.com/haskell@haskell.org/msg07303.html
For a reference to some unificationdriven rewrites, see:
http://www.mailarchive.com/haskell@haskell.org/msg07327.html
Marcin 'Qrczak' Kowalczyk writes:
:
 Assuming that Ints can be implicitly converted to Doubles, is the
 function
 f :: Int > Int > Double > Double
 f x y z = x + y + z
 ambiguous? Because there are two interpretations:
 f x y z = realToFrac x + realToFrac y + z
 f x y z = realToFrac (x + y) + z

 Making this and similar case ambiguous means inserting lots of explicit
 type signatures to disambiguate subexpressions.

 Again, arbitrarily choosing one of the alternatives basing on some
 set of weighting rules is dangerous,
I don't think the following disambiguation is too arbitrary:
x + y + z  as above
> (x + y) + z  leftassociativity of (+)
> realToFrac (x + y) + z  injection (or treating up) done
 conservatively, i.e. only where needed
Regards,
Tom