Haskell 导出枚举的数据基数

Haskell 导出枚举的数据基数,haskell,Haskell,获取派生枚举的数据类型基数的建议方法是什么 --given data ABC = A | B | C deriving (Enum) --want 3 派生有界的 data ABC = A | B | C deriving (Enum, Bounded) 然后minBound::ABC是A,maxBound::ABC是C,fromnum(maxBound::ABC)-fromnum(minBound::ABC)+1是3。这既简单又高效,因此几乎可以肯定是最佳选择 另一种选择: 将{-

获取派生枚举的数据类型基数的建议方法是什么

--given    
data ABC = A | B | C deriving (Enum)
--want 3

派生
有界的

data ABC = A | B | C deriving (Enum, Bounded)
然后
minBound::ABC
A
maxBound::ABC
C
fromnum(maxBound::ABC)-fromnum(minBound::ABC)+1
是3。这既简单又高效,因此几乎可以肯定是最佳选择

另一种选择:

{-#语言派生数据类型表#-}
添加到文件顶部并导入
数据。数据
。然后也为您的类型派生一个
数据的实例。现在
长度。dataTypeConstrs。$(未定义::ABC)
的数据类型为3。这并不太复杂,但可能会慢一点

另一种选择:

启用
{-#语言派生泛型、FlexibleContexts、类型运算符、KindSignatures、DefaultSignatures、ScopedTypeVariables、AllowAmbiguousTypes、TypeApplications#-}
和导入
GHC.Generics
数据.Kind
。定义

class ConCount a where
  conCount :: Int
  -- The Generic constraint here isn't strictly necessary,
  -- but omitting it will tend to lead to inscrutable
  -- error messages for missing Generic instances.
  default conCount :: (Generic a, GConCount (Rep a)) => Int
  conCount = gconCount @(Rep a)

class GConCount (f :: Type -> Type) where
  gconCount :: Int

instance GConCount f => GConCount (M1 i c f) where
  gconCount = gconCount @f

instance GConCount U1 where
  gconCount = 1

instance GConCount V1 where
  gconCount = 0

instance GConCount (a :*: b) where
  gconCount = 1

instance (GConCount f, GConCount g) => GConCount (f :+: g) where
  gconCount = gconCount @f + gconCount @g

instance GConCount (K1 i c) where
  gconCount = 1
现在您可以定义

data ABC = A | B | C deriving Generic

instance ConCount ABC

并使用
conCount@ABC
获取
ABC
中的构造函数数量。这应该是有效的,但它有点过于复杂了。

派生
有界的

data ABC = A | B | C deriving (Enum, Bounded)
然后
minBound::ABC
A
maxBound::ABC
C
fromnum(maxBound::ABC)-fromnum(minBound::ABC)+1
是3。这既简单又高效,因此几乎可以肯定是最佳选择

另一种选择:

{-#语言派生数据类型表#-}
添加到文件顶部并导入
数据。数据
。然后也为您的类型派生一个
数据的实例。现在
长度。dataTypeConstrs。$(未定义::ABC)
的数据类型为3。这并不太复杂,但可能会慢一点

另一种选择:

启用
{-#语言派生泛型、FlexibleContexts、类型运算符、KindSignatures、DefaultSignatures、ScopedTypeVariables、AllowAmbiguousTypes、TypeApplications#-}
和导入
GHC.Generics
数据.Kind
。定义

class ConCount a where
  conCount :: Int
  -- The Generic constraint here isn't strictly necessary,
  -- but omitting it will tend to lead to inscrutable
  -- error messages for missing Generic instances.
  default conCount :: (Generic a, GConCount (Rep a)) => Int
  conCount = gconCount @(Rep a)

class GConCount (f :: Type -> Type) where
  gconCount :: Int

instance GConCount f => GConCount (M1 i c f) where
  gconCount = gconCount @f

instance GConCount U1 where
  gconCount = 1

instance GConCount V1 where
  gconCount = 0

instance GConCount (a :*: b) where
  gconCount = 1

instance (GConCount f, GConCount g) => GConCount (f :+: g) where
  gconCount = gconCount @f + gconCount @g

instance GConCount (K1 i c) where
  gconCount = 1
现在您可以定义

data ABC = A | B | C deriving Generic

instance ConCount ABC

并使用
conCount@ABC
获取
ABC
中的构造函数数量。这应该是有效的,但有点过于复杂。

第一个选项(使用有界)也适用于产品类型吗?@LeifMetcalf,不,不会。因此,这将是使用其他选项之一的一个很好的理由。我们不能为产品类型派生枚举,这是站不住脚的。也许
Bounded
应该有一个
Enum
约束(也不应该
Enum
暗示
Ord
…)。您的最后一个示例应该这样做,在实例
:*:
gconCOunt=gconCOunt@a*gconCOunt@b
中,对吗?看来这就是op想要的。尽管即使如此,它实际上也不算居民。不久前,我浏览了一篇论文,该论文在测试环境中处理了任意ADT的O(1)枚举,具有很好的属性。但愿我能remember@jberryman测试壮举?这不是O(1)(怎么可能),但我相信它是最先进的,而且有一两篇关于它的文章。第一个选项(使用有界)也适用于产品类型吗?@LeifMetcalf,不,不会。因此,这将是使用其他选项之一的一个很好的理由。我们不能为产品类型派生枚举,这是站不住脚的。也许
Bounded
应该有一个
Enum
约束(也不应该
Enum
暗示
Ord
…)。您的最后一个示例应该这样做,在实例
:*:
gconCOunt=gconCOunt@a*gconCOunt@b
中,对吗?看来这就是op想要的。尽管即使如此,它实际上也不算居民。不久前,我浏览了一篇论文,该论文在测试环境中处理了任意ADT的O(1)枚举,具有很好的属性。但愿我能remember@jberryman测试壮举?这不是O(1)(怎么可能),但我相信它是最先进的,而且有一两篇关于它的论文。