我有这样的数据类型:
data ABCS = A Int | B Int | ... | Z Int deriving (Data, Typeable)
在测试中,我想动态提取所有构造函数,从每个构造函数创建一个实例,然后运行测试。
我一直在浏览Data.Typeable
和Data.Data
,但我还没有看到/明白如何从仅以类型(ABC)开始这样做。
非常感谢帮助。
答案 0 :(得分:4)
如果您使用Data.Data
即可,它适用于此用例,但由于Int
参数,它有点笨拙。
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Data
import Data.Typeable
allCtors :: forall a. Data a => [Int -> a]
allCtors = map observeCtor $ dataTypeConstrs $ dataTypeOf (undefined :: a)
where
observeCtor :: Constr -> Int -> a
observeCtor c i = fromJust $ fromConstrM (cast i) c
然后我们就有了。
λ data ABC = A Int | B Int | C Int deriving (Show, Data, Typeable)
data ABC = A Int | B Int | C Int
λ map ($ 2) allCtors :: [ABC]
[A 2,B 2,C 2]
如果您不想使用Data.Data
,则可以使用GHC.Generics
和-XDefaultSignatures
FWIW,如果你能重构ABC以便A,B,C标签是他们自己的类型,你就不必处理任何这个......
data ABCTagged = ABCTagged ABC Int deriving Show
data ABC = A | B | C deriving (Show, Eq, Ord, Enum. Bounded)
...然后只需使用enumFrom minBound :: [ABC]
即可获得整个列表。简单!不确定这对你有多可行。