Shorthand method of enumerating a list a gotcha ... or is it just me?

The problem I see is that in both: Version: September 2006 of hugs, which is the one that is current for Ubuntu 9.10 release, and ghci 6.10.4, they both exhibit a {I think} strange behaviour, in regards to the shorthand way of calling out a list of enumerable values. I will explain the problem that I have run into with examples: Hugs> [3,7..22] [3,7,11,15,19] <- OK Hugs> map (* 1.0) [3,7,11,15,19] <- manual spec OK [3.0,7.0,11.0,15.0,19.0] Hugs> map (* 1.0) [3,7..22] <- same spec as first but !!! when mapped to with a (*1.0) to coerce them to reals: [3.0,7.0,11.0,15.0,19.0,23.0] <- went one outside of range spec. ======================================== Exactly the same behaviour from ghci 6.10.4 : Prelude> [3,7..22] [3,7,11,15,19] Prelude> map (* 1.0) [3,7..22] <- using a range [3.0,7.0,11.0,15.0,19.0,23.0] <- it screws up {at least it is not a "feature' to me} Prelude> map (* 1.0) [3,7,11,15,19] <- spelled out it acts "right". [3.0,7.0,11.0,15.0,19.0] This seems like a possible bug? or at least a sure fire trap waiting to be sprung ... one of those nasties that could really create havoc if someone is not aware of this behaviour and buries a function that include something that unwittingly coerces from an Integral to a Realfrac or Fractional. Is this a well known thing to watch out for.. or is it something that can be worked around, other then having to enumerate every value in a list rather then use the handiness of the range notation as shorthand? cheers, gene

Gene A
The problem I see is that in both: Version: September 2006 of hugs, which is the one that is current for Ubuntu 9.10 release, and ghci 6.10.4, they both exhibit a {I think} strange behaviour, in regards to the shorthand way of calling out a list of enumerable values. I will explain the problem that I have run into with examples:
Hugs> [3,7..22] [3,7,11,15,19] <- OK
Hugs> map (* 1.0) [3,7,11,15,19] <- manual spec OK [3.0,7.0,11.0,15.0,19.0]
Hugs> map (* 1.0) [3,7..22] <- same spec as first but !!! when mapped to with a (*1.0) to coerce them to reals: [3.0,7.0,11.0,15.0,19.0,23.0] <- went one outside of range spec.
[snip]
This seems like a possible bug? or at least a sure fire trap waiting to be sprung ... one of those nasties that could really create havoc if someone is not aware of this behaviour and buries a function that include something that unwittingly coerces from an Integral to a Realfrac or Fractional. Is this a well known thing to watch out for.. or is it something that can be worked around, other then having to enumerate every value in a list rather then use the handiness of the range notation as shorthand?
This is because the Enum instance for floating point numbers is screwy and shouldn't be used in general (floating point rounding, etc.; don't forget, they're defined in binary and not all fractional values can be defined exactly in a finite binary value). A better way: map fromIntegral [3,7..22] -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

Hugs> [3,7..22] [3,7,11,15,19] <- OK
Hugs> map (* 1.0) [3,7..22] <- same spec as first but !!! when mapped to with a (*1.0) to coerce them to reals: [3.0,7.0,11.0,15.0,19.0,23.0] <- went one outside of range spec.
This is because the Enum instance for floating point numbers is screwy and shouldn't be used in general
I think the original poster is probably being confused by the fact that the first mention of [3,7..22] looks identical to the second mention, but they are given different types by Haskell. The literal '3', although it looks like an integer, is being given the type Double in the second list enumeration, because of the context of needing to multiply it by 1.0. The comment mentions coercion, as if the list is generated at type Integer, and then converted to Double, but that is not the case. It is generated at type Double, and no coercion happens. Regards, Malcolm

An easier way of demonstrating this issue:
Prelude> [3,7..22]::[Int]
[3,7,11,15,19]
Prelude> [3,7..22]::[Double]
[3.0,7.0,11.0,15.0,19.0,23.0]
/Jonas
On 8 May 2010 09:47, Malcolm Wallace
Hugs> [3,7..22] [3,7,11,15,19] <- OK
Hugs> map (* 1.0) [3,7..22] <- same spec as first but !!! when mapped to with a (*1.0) to coerce them to reals: [3.0,7.0,11.0,15.0,19.0,23.0] <- went one outside of range spec.
This is because the Enum instance for floating point numbers is screwy and shouldn't be used in general
I think the original poster is probably being confused by the fact that the first mention of [3,7..22] looks identical to the second mention, but they are given different types by Haskell. The literal '3', although it looks like an integer, is being given the type Double in the second list enumeration, because of the context of needing to multiply it by 1.0. The comment mentions coercion, as if the list is generated at type Integer, and then converted to Double, but that is not the case. It is generated at type Double, and no coercion happens.
Regards, Malcolm
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

From the Haskell 98 report (section 6.3.4):
For Float and Double, the semantics of the enumFrom family is given by the rules for Int above, except that the list terminates when the elements become greater than e3+i/2 for positive increment i, or > when they become less than e3+i/2 for negative i.
So yes, it is surprising, but according to the specification. But then again the very concept of a type like Float having an Enum instance is a bit weird.
participants (5)
-
Gene A
-
Ivan Lazar Miljenovic
-
Jonas Almström Duregård
-
Malcolm Wallace
-
Roel van Dijk