首页 > 解决方案 > 数据派生枚举的基数

问题描述

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

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

标签: haskell

解决方案


推导Bounded也行。

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

然后minBound :: ABCis A, maxBound :: ABCis C, and fromEnum (maxBound :: ABC) - fromEnum (minBound :: ABC) + 1is 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. 这应该是有效的,但它有点过于复杂了。


推荐阅读