数据派生枚举的基数

时间:2018-12-30 02:07:32

标签: haskell

建议使用什么方法来获取派生枚举的数据类型的基数。

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

1 个答案:

答案 0 :(得分:7)

也派生Bounded

data ABC = A | B | C deriving (Enum, Bounded)

然后minBound :: ABCAmaxBound :: ABCC,而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.GenericsData.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中的构造函数数。这应该是有效的,但是有点过于复杂了。