I was a bit surprised to learn that Haskell defines its succ
function on numbers as adding one:
succ :: a -> a
The successor of a value. For numeric types, succ adds 1.
Although for integral values, this seems reasonable there are a few problems:
First of all, it means that [2.0 :: Float .. 3.0 :: Float]
(used :: Float
to make sure the call is not ambiguous) only contains integral values added to the original value, whereas if one uses this expression he/she might expect the list will include all floating points between the two values; of course this argument is more about what one prefers. Most programmers don't have much problems with this aspect.
More severely, if one uses the expression [2.2 :: Float .. 4.0 :: Float]
it results in [2.2,3.2,4.2]
what is 4.2
doing here?
If one uses a floating point number where +1
cannot generate a different number (because the mantissa doesn't have enough bits to represent one anymore), it will loop infinitely. For instance:
Prelude> [1e37 :: Float .. 1e37 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
Prelude> [1e37 :: Float .. 1e37-1 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
Prelude> [1e37 :: Float .. 1e37+1 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
Prelude> [1e37 :: Float .. pred 1e37 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
One thus generates an infinite amount of values, even if the list ought to be empty or contain a few elements.
Part of the arguments are indeed a bit nitpicking, but at least for some, it is reasonable to assume that a Haskell programmer will eventually make mistakes.
Wouldn't a more reasonable approach have been to generate the next representable floating point number?
What were the arguments to define succ
in such way? Is it reasonable that Float
is an instance of Enum
?
The origin of the succ
function itself actually has nothing to do with the Haskell data types or enumerations, in fact the succ
function came first. The succ
function is actually the successor function in the axiom of infinity which allows us to create numbers in the first place. It was never designed to be used with floating point/non-natural numbers, that's why you're encountering this problem.
It would probably be a good idea to modify the succ
function for floating point types in Haskell, you ought to submit something to the mailing list about it. Although, Haskell is standardized in the Haskell98 report so don't get your hopes up about changing the language.
Only read the following if you are familiar with Haskell's type classes: You mention different possible uses of the succ
function, this is why it is defined as a function for the Enum
type class. Therefore you can easily rebind it to do something different with a newtype
.