我最近一直试图“学习一个Haskell”,我想创建一个表示整数状态的新类型,而不仅仅使用原始Integer(用于类型安全和代码清晰度)。具体来说,以下代码编译:
newtype AuxState = AuxState Integer
deriving (Eq, Ord, Num, Integral, Real, Enum)
但是,由于我的应用程序中存在无数个状态,因此我没有兴趣将此状态转换为Enum。但是,如果我尝试删除deriving (Enum)
语句,只是deriving (Eq, Ord, Num, Integral, Real)
,编译器会抱怨:
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)
我发现很难相信Haskell强制Integral类中的一个类型也在Enum类中;不应该只是反过来?这有什么理由,还是我在做/理解错误?
答案 0 :(得分:8)
所有Integral
必须Enum
,因为Integral
数学的基础是succ
和pred
操作。 (技术上Enum
代表一个正确的类型层次结构,其中Integral
类型是一个数学半群,我认为。)反过来似乎更错误:你的意思是每个Enum
应该Integral
?这是否包括随机ADT,如
data Foo = A | B | C | D | E | F | G deriving (Enum)
(每个Enum
应该与Integral
的子集同构,但实际上这表明它朝另一个方向:Integral
可以代表任何Enum
但不是反之亦然,所以Integral
就像你的那样 - Enum
。)
答案 1 :(得分:6)
技术原因是因为Integral
中的Prelude
定义如下:
class (Real a, Enum a) => Integral a where
...
数学原因是每个整数类型都是可枚举的,但反之亦然。例如,考虑有理数。请注意,Enum并不意味着有限枚举,如Integer
所示。