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

bto*_*own 5 haskell

我最近一直试图"学习一个Haskell",我想创建一个表示整数状态的新类型,而不仅仅使用原始的Integer(用于类型安全和代码清晰度).具体来说,以下代码编译:

newtype AuxState = AuxState Integer
  deriving (Eq, Ord, Num, Integral, Real, Enum)
Run Code Online (Sandbox Code Playgroud)

但是,由于我的应用程序中存在无数个状态,因此我没有兴趣将此状态转换为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)
Run Code Online (Sandbox Code Playgroud)

我发现很难相信Haskell强制Integral类中的一个类型也在Enum类中; 不应该只是反过来?这有什么理由,还是我在做/理解错误?

gee*_*aur 8

一切Integral都是Enum因为Integral数学的基础是succpred操作.(从技术上讲,我认为Enum一种Integral类型是数学半群的正确类型层次结构.)另一种方式看起来更加错误:你的意思是每一个都Enum应该是Integral?这是否包括随机ADT

data Foo = A | B | C | D | E | F | G deriving (Enum)
Run Code Online (Sandbox Code Playgroud)

(当然,每个都Enum应该与同一个子集同构Integral,但实际上这表明它会向另一个方向发展:Integral可以代表任何方向,Enum但不能反过来,所以就像你的 Integral那样Enum.)


jmg*_*jmg 6

技术原因是因为Integral定义Prelude如下:

class (Real a, Enum a) => Integral a where
   ...
Run Code Online (Sandbox Code Playgroud)

数学原因是每个整数类型都是可枚举的,但反之亦然.例如,考虑有理数.注意,Enum并不意味着有限的枚举,如图所示Integer.