5
votes

I've recently been trying to "learn me a Haskell," and I'd like to create a new type to represent an integer state, without just using a raw Integer (for type safety and code clarity). Specifically, the following code compiles:

newtype AuxState = AuxState Integer
  deriving (Eq, Ord, Num, Integral, Real, Enum)

However, since there are an infinite number of states in my application, I have no interest in converting this state into an Enum. However, if I try to remove the deriving (Enum) statement so it's just deriving (Eq, Ord, Num, Integral, Real), the compiler complains:

No instance for (Enum AuxState)
  arising from the 'deriving' clause of a data type declaration
Possible fix:
  add an instance declaration for (Enum AuxState)
  or use a standalone 'deriving instance' declaration,
       so you can specify the instance context yourself
When deriving the instance for (Integral AuxState)

I find it hard to believe that Haskell forces a type in the Integral class to also be in the Enum class; shouldn't it just be the other way around? Is there a reason for this, or am I doing/understanding something wrong?

2
Enum instances are sequentially ordered types—their values can be enumerated. The main advantage of the Enum type class is that we can use its values in list ranges. They also have defined successors and predecessors, which we can get with the succ and pred fuctions. I believe all integers should belong to this class, why shouldn't yours? - Edwin Dalorzo
"However, since there are an infinite number of states in my application, ..." I think you have a wrong understanding of Enum. Enum does not mean a type with a finite number of values. - newacct
"shouldn't it just be the other way around?" Double is an Enum, but obviously not Integral - newacct
Echoing newacct's statement, you seem to be mixing the concept of Bounded with Enum. For example, Integer is an Enum but is not Bounded. - Dan Burton
@edalorzo That's exactly the answer I was looking for. I think I had had a wrong idea of what Enum meant, that it was a characteristic of types declared as A | B | C | D, but it's actually a much more general set of characteristics. - btown

2 Answers

8
votes

All Integral are necessarily Enum because the foundations of Integral math are the succ and pred operations. (Technically Enum is standing in for a proper type hierarchy where an Integral type is a mathematical semigroup, I think.) The other way around seems even more wrong: you mean that every Enum should be Integral? Does this include random ADTs like

data Foo = A | B | C | D | E | F | G deriving (Enum)

?

(Every Enum should be isomorphic to a subset of Integral, surely, but that actually suggests it going the other direction: Integral can represent any Enum but not vice versa, so Integral is kind of the ur-Enum.)

6
votes

The technical reason is because is because Integral is defined in Prelude as follows:

class (Real a, Enum a) => Integral a where
   ...

The mathematical reason is that every integral type is enumerable but not vice versa. Think about rational numbers for example. Note, that Enum does not imply finite enumeration as is shown by Integer.