Haskell анализирует имена и типы полей записи - PullRequest
9 голосов
/ 31 декабря 2011

Основываясь на недавнем обмене , я был убежден, что использую Template Haskell для генерации некоторого кода для обеспечения безопасности типов во время компиляции.

Мне нужно проанализировать имена полей записей итипы.Я понимаю, что могу получить имена полей , используя constrFields . toConstr :: Data a => a -> [String].Но мне нужно больше, чем имена полей, мне нужно знать их тип.Например, мне нужно знать имена полей типа Bool.

Как мне создать функцию f :: a -> [(String, xx)], где a - это запись, String - это имя поля иxx это тип поля?

1 Ответ

10 голосов
/ 31 декабря 2011

Тип должен быть доступен вместе со всем остальным в значении Info, предоставленном reify. В частности, вы должны получить TyConI, который содержит a Dec значение , из которого вы можете получить список 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)

Импортируя это в другой модуль, мы можем использовать его так:

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

foo = $(test ''Foo)

При загрузке в GHCi значение в foo равно [("Foo",[("foo1","ConT GHC.Types.Int"),("foo2","ConT GHC.Types.Bool")])].

Это дает вам грубую идею?

...