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