Ana*_*Ana 9 haskell template-haskell
基于最近的交换,我已经确信使用Template Haskell生成一些代码来确保编译时类型的安全性.
我需要内省记录字段名称和类型.我知道我可以通过使用获得字段名称constrFields . toConstr :: Data a => a -> [String].但我需要的不仅仅是字段名称,我需要知道它们的类型.例如,我需要知道类型字段的名称Bool.
如何构建函数f :: a -> [(String, xx)]where athe record,String是字段名称xx还是字段类型?
C. *_*ann 10
该类型应与其提供的Info值一起提供reify.具体来说,您应该获得一个TyConI包含值的aDec,您可以从中获取Con指定构造函数的值列表.然后应该使用记录类型RecC,它将为您提供由包含字段名称的元组描述的字段列表,字段是否严格以及类型.
你去哪里取决于你想要做什么.
编辑:为了实际演示上面的内容,这里有一个非常糟糕的快速和脏的函数,可以找到记录字段:
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)
Run Code Online (Sandbox Code Playgroud)
在另一个模块中导入它,我们可以像这样使用它:
data Foo = Foo { foo1 :: Int, foo2 :: Bool }
foo = $(test ''Foo)
Run Code Online (Sandbox Code Playgroud)
加载在GHCI,在价值foo的[("Foo",[("foo1","ConT GHC.Types.Int"),("foo2","ConT GHC.Types.Bool")])].
这会给你一个粗略的想法吗?