在reify 提供的Info 值中应该可以使用该类型以及其他所有内容。具体来说,你应该得到一个TyConI,其中包含a Dec value,你可以从中得到Con values specifying the constructors的列表。然后记录类型应该使用RecC,这将为您提供包含字段名称、字段是否严格以及the type 的字段列表described by a tuple。
你从那里去哪里取决于你想用这一切做什么。
编辑:为了实际演示上述内容,这里有一个非常糟糕的快速而肮脏的函数,它可以找到记录字段:
import Language.Haskell.TH
test :: Name -> Q Exp
test n = do rfs <- fmap getRecordFields $ reify n
litE . stringL $ show rfs
getRecordFields :: Info -> [(String, [(String, String)])]
getRecordFields (TyConI (DataD _ _ _ cons _)) = concatMap getRF' cons
getRecordFields _ = []
getRF' :: Con -> [(String, [(String, String)])]
getRF' (RecC name fields) = [(nameBase name, map getFieldInfo fields)]
getRF' _ = []
getFieldInfo :: (Name, Strict, Type) -> (String, String)
getFieldInfo (name, _, ty) = (nameBase name, show ty)
在另一个模块中导入它,我们可以这样使用它:
data Foo = Foo { foo1 :: Int, foo2 :: Bool }
foo = $(test ''Foo)
在 GHCi 中加载,foo 中的值为[("Foo",[("foo1","ConT GHC.Types.Int"),("foo2","ConT GHC.Types.Bool")])]。
这会给你一个粗略的想法吗?