I don't mind doing this, but can someone first give a brief justification about why it's a good idea, independent of the discussion that has taken place on this list? I'd like to add such an explanation to the code. Simon | -----Original Message----- | From: qrczak@knm.org.pl [mailto:qrczak@knm.org.pl] | Sent: 16 February 2001 17:42 | To: haskell-cafe@haskell.org | Subject: Re: Primitive types and Prelude shenanigans | | | Thu, 15 Feb 2001 20:56:20 -0800, William Lee Irwin III | <wli@holomorphy.com> pisze: | | > literal "5" gets mapped to (fromPositiveInteger 5) | > literal "-9" gets mapped to (fromNonZeroInteger -9) | | Note that when a discussed generic Prelude replacement | framework is done, and ghc's rules are changed to expand -9 to | negate (fromInteger 9) instead of fromInteger (-9), then you don't | need uglification of the fromInteger function to be able to define | types with only nonnegative numeric values. Just define your negate | in an appropriate class, different from the fromInteger's class. | | -- | __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ | \__/ | ^^ SYGNATURA ZASTEPCZA | QRCZAK | | | _______________________________________________ | Haskell-Cafe mailing list | Haskell-Cafe@haskell.org | http://www.haskell.org/mailman/listinfo/haskell-cafe |
Tue, 20 Feb 2001 08:33:46 -0800, Simon Peyton-Jones <simonpj@microsoft.com> pisze:
I don't mind doing this, but can someone first give a brief justification about why it's a good idea, independent of the discussion that has taken place on this list?
Suppose we build an alternative Prelude with different numeric class hierarchy, and decide that types for natural numbers should not have 'negate' defined, as it's obviously meaningless for them. We can put 'fromInteger' in some class and 'negate' in its subclass, and make only the former instance for natural numbers. So -9 :: Natural should be a compile error. Negation is already an error for all expressions other than literals when negate has a wrong type for them; literals should not be an exception. Negated literals are still treated in a special way in patterns, but -9 in a pattern should expand to testing equality with negate (fromInteger 9), not fromInteger (-9), to catch types which intentionally don't have negate defined. -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK
On 20-Feb-2001, Simon Peyton-Jones <simonpj@microsoft.com> wrote:
I don't mind doing this, but can someone first give a brief justification about why it's a good idea, independent of the discussion that has taken place on this list? I'd like to add such an explanation to the code.
How about "Because the Haskell 98 Report says so"? ;-) It's a pity there's no Haskell 98 Rationale, like the Ada 95 Rationale... if there was, then the documentation in the ghc code could just point at it. ---------- There is however one issue with this change that concerns me. I'm wondering about what happens with the most negative Int. E.g. assuming 32-bit Int (as in Hugs and ghc), what happens with the following code? minint :: Int minint = -2147483648 I think the rules in the Haskell report mean that you need to write that example as e.g. minint :: Int minint = -2147483647 - 1 ghc currently allows the original version, since it treats negative literals directly, rather than in the manner specified in the Haskell report. ghc also allows `(negate (fromInteger 2147483648)) :: Int', apparently because ghc's `fromInteger' for Int just extracts the bottom bits (?), so changing ghc to respect the Haskell report's treatment of negative literals won't affect this code. But the code does not work in Hugs, because Hugs follows the Haskell report's treatment of negative literals, and the `fromInteger' in Hugs does bounds checking -- Hugs throws an exception from `fromInteger'. The documentation in the Haskell report does not say what `fromInteger' should do for `Int', but the Hugs behaviour definitely seems preferable, IMHO. However, this leads to the unfortunate complication described above when writing a literal for the most negative Int. Of course using `minBound' is a much nicer way of finding out the minumum integer, at least in hand-written code. But this issue might be a potential pitfall for programs that automatically generate Haskell code. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
Wed, 21 Feb 2001 12:55:37 +1100, Fergus Henderson <fjh@cs.mu.oz.au> pisze:
The documentation in the Haskell report does not say what `fromInteger' should do for `Int', but the Hugs behaviour definitely seems preferable, IMHO.
Sometimes yes. But for playing with Word8, Int8, CChar etc. it's sometimes needed to just cast bits without overflow checking, to convert between "signed bytes" and "unsigned bytes". -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK
On 21-Feb-2001, Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> wrote:
Wed, 21 Feb 2001 12:55:37 +1100, Fergus Henderson <fjh@cs.mu.oz.au> pisze:
The documentation in the Haskell report does not say what `fromInteger' should do for `Int', but the Hugs behaviour definitely seems preferable, IMHO.
Sometimes yes. But for playing with Word8, Int8, CChar etc. it's sometimes needed to just cast bits without overflow checking, to convert between "signed bytes" and "unsigned bytes".
Both are desirable in different situations. But if you want to ignore overflow, you should have to say so explicitly. `fromInteger' is implicitly applied to literals, and implicit truncation is dangerous, so `fromInteger' should not truncate. There should be a different function for conversions that silently truncate. You can implement such a function yourself, of course, e.g. as follows: trunc :: (Bounded a, Integral a) => Integer -> a trunc x = res where min, max, size, modulus, result :: Integer min = toInteger (minBound `asTypeOf` res) max = toInteger (maxBound `asTypeOf` res) size = max - min + 1 modulus = x `mod` size result = if modulus > max then modulus - size else modulus res = fromInteger result But it is probably worth including something like this in the standard library, perhaps as a type class method. -- Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
participants (3)
-
Fergus Henderson -
qrczak@knm.org.pl -
Simon Peyton-Jones