Info
タイプは、によって提供される値で、他のすべてと一緒に使用できる必要がありますreify
。具体的には、valueTyConI
を含むを取得する必要があります。そこから、コンストラクターを指定する値のリストを取得できます。次に、レコード タイプは を使用する必要があります。これにより、フィールド名、フィールドが厳密かどうか、タイプを含むタプルによって記述されるフィールドのリストが得られます。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")])]
。
それはあなたに大まかなアイデアを与えますか?