fromInteger :: Integer -> Int/Word

Under Hugs, fromInteger (and thus fromIntegral) throws an exception if the argument is outside the representable range of values, while GHC just truncates. And some of the libraries rely on the GHC behaviour. It seems it's not a matter of principle with Hugs, since operations on Int or Word silently overflow, as do the built-in conversions between Int and Word types.

Ross Paterson
Under Hugs, fromInteger (and thus fromIntegral) throws an exception if the argument is outside the representable range of values, while GHC just truncates.
I would say that GHC implements a performance optimization by dropping the check and that the behaviour outside the range of Int should be treated as undefined (which is not the same as 'implementation defined').
And some of the libraries rely on the GHC behaviour.
I would say that such code is broken since it relies on a non-portable feature. I use 'non-portable' both in the sense that code depends on a quirk of one implementation and in the sense that the code will behave differently on different architectures.
It seems it's not a matter of principle with Hugs, since operations on Int or Word silently overflow,
It is hard to write portable C code which detects integer overflow for addition, multiplication, division, etc. so Hugs punts in this exceptional case.
as do the built-in conversions between Int and Word types.
I think that would be easy to fix and should be done. (Alternatively, one could argue that since Int and Word are required to have the same bit size, the conversion should follow the same pattern as for Int<m> <-> Word<n> where m==n. I prefer to regard Int and Word as types whose portability issues should be brought to the users attention as often as possible in the hope that they will be encouraged to think about writing their code using portable types.) In general, I think libraries should be restricted to that behaviour which can be provided in a portable way and, where feasible, libraries should check that they are used in that portable way. Exceptions to this are where the test is hard to implement or maintain or interfere with other goals of the compiler (speed for GHC, portability for Hugs). -- Alastair Reid alastair@reid-consulting-uk.ltd.uk Reid Consulting (UK) Limited http://www.reid-consulting-uk.ltd.uk/alastair/ ps This reminds me: I should add code to detect when 'unsafe' ffi calls and finalizers call back into the Hugs evaluator. Also, we should treat all ffi calls inside a call to unsafePerformIO as 'unsafe' since they cannot safely reenter the Hugs evaluator (for the same reason that finalizers are not allowed to).

On Wed, Apr 09, 2003 at 04:21:34PM +0100, Alastair Reid wrote:
Ross Paterson
writes: Under Hugs, fromInteger (and thus fromIntegral) throws an exception if the argument is outside the representable range of values, while GHC just truncates.
I would say that GHC implements a performance optimization by dropping the check and that the behaviour outside the range of Int should be treated as undefined (which is not the same as 'implementation defined').
OK, consider conversions between Int<n> and Word<n>, where the documented behaviour (in Data.Int and Data.Word) is to preserve representation. If you concede that, then since this conversion goes through fromInteger, it would need to accept at least the range -2^(n-1)..2^n-1 for both types. Stopping there would be hard to explain, but I suppose it would achieve your aim of unpredictable harassment of people who use these types nonportably.
And some of the libraries rely on the GHC behaviour.
I would say that such code is broken since it relies on a non-portable feature.
The example I came across was System.Posix.IO.fdRead, where a read call is declared as returning CSize (= Word32), and put inside throwErrnoIfMinus1Retry, resulting in fromInteger (-1) :: Word32. I guess the neat thing would need a Haskell equivalent of Posix's ssize_t type, but the version there is legal according to the documented behaviour.
participants (2)
-
Alastair Reid
-
Ross Paterson