
On Tue, Sep 20, 2011 at 11:29 PM, Richard O'Keefe
On 21/09/2011, at 2:59 AM, Chris Smith wrote:
On Mon, 2011-09-19 at 22:09 -0700, Evan Laforge wrote:
Then I tried switching to a fixed point format, and discovered my mistake. Enum is supposed to enumerate every value between the two points, and the result is memory exhaustion.
% ghci Prelude> [1.0..2.0]::[Double] [1.0,2.0]
(..) for Doubles is using (+1), not nextAfter, and is NOT enumerating every value between 1.0 and 2.0
import Ratio Prelude Ratio> [1%2..7%2] :: [Ratio Int] [1 % 2,3 % 2,5 % 2,7 % 2]
(..) for (Ratio a) is using (+1), and is NOT enumerating the infinitely many values between 1.5 and 3.5.
Why should your fixed point format behave any differently?
Evan's claim was that Double and Ratio are doing the incorrect thing; the evidence you gave may support your point, but it supports his as well. My claim now, and I think Evan agrees although I am not sure, is that Double and Ratio shouldn't be instances of Enum at all, since enumerating (a simulation of) the reals and enumerating the rationals in order is nonsensical. I also find that toEnum . fromEnum /= id annoying; anything that relies on it, like EnumSet/EnumMap [1], goes down the toilet. Other things I think are reasonable to expect are also broken; for example, toEnum . succ . fromEnum /= succ (granted, it is reasonable to expect this to be broken considering that toEnum . fromEnum is broken). With fixed point numbers, it makes sense to have an Enum instance. Enumeration is reasonable because most applications for fixed point arithmetic do *not* want to pretend that they are real numbers; you almost always want to be aware of the current precision and whether you might overflow or need more precision. This situation is no different from Word or Int. toEnum and fromEnum are also inverses. No expectations are violated here unless you have already gotten used to the broken Float, Double, and Rational instances. - Jake [1] http://www.haskell.org/haskellwiki/EnumSet_EnumMap