建议使用什么方法来获取派生枚举的数据类型的基数。
--given
data ABC = A | B | C deriving (Enum)
--want 3
答案 0 :(得分:7)
也派生Bounded
。
data ABC = A | B | C deriving (Enum, Bounded)
然后minBound :: ABC
为A
,maxBound :: ABC
为C
,而fromEnum (maxBound :: ABC) - fromEnum (minBound :: ABC) + 1
为3。这是简单有效的方法,因此几乎可以肯定是最佳选择
另一个选择:
将{-# language DeriveDataTypeable #-}
添加到文件顶部,然后导入Data.Data
。然后也为您的类型派生一个Data
的实例。现在length . dataTypeConstrs . dataTypeOf $ (undefined :: ABC)
是3。这虽然不太复杂,但可能会更慢。
另一个选择:
启用{-# language DeriveGeneric, FlexibleContexts, TypeOperators, KindSignatures, DefaultSignatures, ScopedTypeVariables, AllowAmbiguousTypes, TypeApplications #-}
并导入GHC.Generics
和Data.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
中的构造函数数。这应该是有效的,但是有点过于复杂了。