Hans Aberg writes:
> >From the mathematical point of view, let Z denote the mathematical
> integers; then there are two interpretations of Int, as a ring R = Z/N, N =
> 2^n, and as a segment I = [minBound , maxBound] of integers from Z.
>
> Here, we could identify Z = Integer. If we set Int = R, then the natural
> type conversion Integer -> Int is the canonical homomorphism Z -> R
> (corresponding to taking the remainder attained by division by N). If we
> set Int = I, then one should throw an exception when the computations goes
> out of bounds.
>
> So it seems that one has not given sufficiently much thought of what
> mathematical structure Int should have.
I disagree that we haven't given enough thought to what structure we
want - I think all the Hugs and GHC hackers know the choices. I think
the problem is that we can't agree on what we want. In some
circumstances, an error is appropriate and in others an exception is
appropriate.
However, your mail does remind me that we have {Word,Int}32 and
friends for use when we do want to calculate modulo 2^32 - converting
to them should certainly not give exceptions. This is what Sigbjorn
(I think it was he who raised the issue) should have been using if he
was relying on not getting exceptions.
> My guess is that Int should behave as R, and then one should use the
> canonical homomorphism Z -> R for type conversion.
One of the problems with this choice is that the Haskell standard
doesn't guarantee the value of N and we can reasonably expect it to
vary with processor word size and perhaps with garbage collector (eg
Yale Haskell used 31 bit ints instead of 32 bit ints). This is why we
added {Int,Word}{8,16,32,64} - so that you'd know what you were
dealing with and could write portable code.
> The variation where Int = I, I think is not of much use in
> computers, in view of the overhead keeping track of arithmetic
> errors create. But it could surely be added as a special structure.
In most cases, this is true (and that usually tips the balance in
favour of nto checking for overflow) but, in this case, the overhead
is fairly small since the Z->I coercion is already relatively
expensive due to the representations we use.
I think the Z->I coercion should raise an exception - it's easy and
cheap to add.
Alastair
ps One tiny detail: does "raise an exception" mean "abort the program"
or "raise a catchable exception". In the long term, we obviously want
the latter but I don't think either GHC or Hugs is especially good or
consistent about only raising catchable exceptions so, for now, it
might be acceptable to abort if that is significantly easier. At some
point, someone's going to have to go over both systems with a
fine-tooth comb looking for aborts that should be exceptions - so
absolute consistency can probably be put off till then.