Typ powinien być dostępny, wraz ze wszystkim innym, w wartości Info
dostarczonej przez reify
. W szczególności powinieneś uzyskać numer TyConI
, który zawiera a Dec
value, z którego możesz uzyskać listę Con
values specifying the constructors. Typ rekordu powinien następnie użyć RecC
, co da ci listę pól described by a tuple zawierającą nazwę pola, czy pole jest ścisłe, i the type.
Dokąd pójdziesz, zależy od tego, co chcesz zrobić z tym wszystkim.
Edit: Dla faktycznie wykazując wyżej, tutaj jest naprawdę straszny szybki i brudny funkcją, która wyszukuje pola rekordu:
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)
Importowanie że w innym module, możemy go użyć tak:
data Foo = Foo { foo1 :: Int, foo2 :: Bool }
foo = $(test ''Foo)
Ładowanie że w GHCi wartość w foo
jest [("Foo",[("foo1","ConT GHC.Types.Int"),("foo2","ConT GHC.Types.Bool")])]
.
Czy to daje zły pomysł?
Dokładnie tego szukam. Przygotowałem twój przykład do następujących rzeczy: 'introspect n = reify n >> = stringE. show'. Dzięki za wskazówki! – Ana