Implementation of `enumFromTo` for `Float` seems confusing in behavior
Summary
The implementation of enumFromThenTo/enumFromTo/etc… evaluates start + k·step for a value k starting at 0, incremented by 1 each step.
For expressions [a :: Float .. b], this results in unexpected behavior when the value k reaches 224, because k itself is a Float as-well. The value 224 is about 16 million, so it can be reached in less than 3 seconds on modern hardware.
Steps to reproduce
Inspect the list [-16000000 :: Float .. 1000000],
e.g. by evaluating
take 30 $ dropWhile (< 777210) [-16000000 :: Float .. 1000000]
or trying to determine
length [-16000000 :: Float .. 1000000]
Expected behavior
Especially considering that both -16000000 and +1000000 are well withing the range that Float supports on a
precision level where every integer is still precisely representable, one would expect that [-16000000 :: Float .. 1000000] is a finite list.
Consequently one would expect length [-16000000 :: Float .. 1000000] to terminate – it doesn’t – and one would expect
take 30 $ dropWhile (< 777210) [-16000000 :: Float .. 1000000] to evaluate to
[777210.0,777211.0,777212.0,777213.0,777214.0,777215.0,777216.0,777217.0,777218.0,777219.0,777220.0,777221.0,777222.0,777223.0,777224.0,777225.0,777226.0,777227.0,777228.0,777229.0,777230.0,777231.0,777232.0,777233.0,777234.0,777235.0,777236.0,777237.0,777238.0,777239.0]
– yet it returns
[777210.0,777211.0,777212.0,777213.0,777214.0,777215.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0,777216.0]
Environment
Environment should be irrelevant, the relevant implementation is in https://gitlab.haskell.org/ghc/ghc/-/blob/98aa29d3fe447cce3407e6864b015892244bb475/libraries/base/GHC/Real.hs#L273-L279