unexpected arithmetic sequence and deriving Enum behaviour
Simon Marlow
simonmarhaskell at gmail.com
Fri Jun 30 12:10:14 EDT 2006
Hi Laszlo,
Laszlo Nemeth wrote:
> Consider the following code fragment:
>
> data Colour = Red | Black | Blue deriving (Show, Bounded)
>
> instance Enum Colour where
> succ Red = Black
> succ Black = Blue
> succ Blue = error "succ of maxBound"
>
> fromEnum Red = 1
> fromEnum Black = 2
> fromEnum Blue = 3
>
> toEnum 1 = Red
> toEnum 2 = Black
> toEnum 3 = Blue
> toEnum n = error ("? "++show n)
>
> main = do print $ [Red ..]
>
> Notice that there is no deriving Enum (which would be an error according
> to the Report)
Why do you say that? Can you give a pointer to the relevant text in the
report? I can't see anything wrong here.
The minimal complete instance of Enum consists of toEnum and fromEnum,
which yours does.
> and there is no definition for 'enumFrom'.
>
> So, in the first place I'd expect a warning for main for the use of the
> arithmetic sequence, something about a missing definition. There isn't
> one, and the program compiles. Interestingly, -ddump-deriv doesn't show
> anything about deriving instances for Colour, yet, obviously something
> gets derived.
>
> When you run it, it dies with an error message from 'toEnum n' (or
> non-exhaustive pattern if you leave that one out). Looking at core
> reveals the reason for this:
>
[ core snipped ]
>
> The max bound which gets used is the one for Int, not for Colour!
This is because, as per the report, GHC defines the default method for
enumFrom as:
enumFrom x = map toEnum [fromEnum x ..]
the sequence on the RHS is at type Int, and hence doesn't terminate
until it reaches maxBound::Int.
Perhaps you expect that, because your type is also an instance of
Bounded, that enumFrom should behave differently. However, there can
only be one default method for enumFrom.
> Perhaps this isn't a bug, but definitely an undocumented and rather
> unexpected 'feature'. This is with ghc-6.4 onwards, and I haven't
> checked earlier versions.
You're right, I don't think it's a bug. Also, if you had derived Enum
instead of defining it, you would have got a version that behaved in the
"expected" way. You defined an instance of Enum yourself, and got
exactly what you asked for!
Cheers,
Simon
More information about the Glasgow-haskell-bugs
mailing list