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)(怎么可能),但我相信它是最先进的,而且有一两篇关于它的论文。