为什么Haskell类型“派生积分”需要“导出枚举”?

时间:2012-04-11 04:28:25

标签: haskell

我最近一直试图“学习一个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类中;不应该只是反过来?这有什么理由,还是我在做/理解错误?

2 个答案:

答案 0 :(得分:8)

所有Integral必须Enum,因为Integral数学的基础是succpred操作。 (技术上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所示。