Question

Based on a recent exchange, I've been convinced to use Template Haskell to generate some code to ensure compile-time type safety.

I need to introspect record field names and types. I understand I can get field names by using constrFields . toConstr :: Data a => a -> [String]. But I need more than the field names, I need to know their type. For example, I need to know the names of fields that are of type Bool.

How do I construct a function f :: a -> [(String, xx)] where a is the record, String is the field name and xx is the field type?

Was it helpful?

Solution

The type should be available, along with everything else, in the Info value provided by reify. Specifically, you should get a TyConI, which contains a Dec value, from which you can get the list of Con values specifying the constructors. A record type should then use RecC, which will give you a list of fields described by a tuple containing the field name, whether the field is strict, and the type.

Where you go from there depends on what you want to do with all this.


Edit: For the sake of actually demonstrating the above, here's a really terrible quick and dirty function that finds record fields:

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)

Importing that in another module, we can use it like so:

data Foo = Foo { foo1 :: Int, foo2 :: Bool }

foo = $(test ''Foo)

Loading that in GHCi, the value in foo is [("Foo",[("foo1","ConT GHC.Types.Int"),("foo2","ConT GHC.Types.Bool")])].

Does that give you the rough idea?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top