Loại phải có sẵn cùng với mọi thứ khác, trong giá trị Info
do reify
cung cấp. Cụ thể, bạn sẽ nhận được TyConI
, có chứa a Dec
value, từ đó bạn có thể nhận danh sách Con
values specifying the constructors. Một loại bản ghi sau đó sẽ sử dụng RecC
, sẽ cung cấp cho bạn danh sách các trường described by a tuple chứa tên trường, cho dù trường đó là nghiêm ngặt và the type.
Nơi bạn đi từ đó phụ thuộc vào những gì bạn muốn làm với tất cả điều này.
Sửa: Vì lợi ích của thực sự chứng minh ở trên, đây là một chức năng nhanh chóng và dơ bẩn thực sự khủng khiếp mà thấy lĩnh vực kỷ lục:
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)
Nhập rằng trong mô-đun khác, chúng tôi có thể sử dụng nó như vậy:
data Foo = Foo { foo1 :: Int, foo2 :: Bool }
foo = $(test ''Foo)
Tải trong GHCi, giá trị trong foo
là [("Foo",[("foo1","ConT GHC.Types.Int"),("foo2","ConT GHC.Types.Bool")])]
.
Điều đó có cung cấp cho bạn ý tưởng thô không?
Đó chính xác là những gì tôi đang tìm kiếm. Tôi luộc ví dụ của bạn xuống dưới đây: 'introspect n = reify n >> = stringE. show'. Cảm ơn bạn đã hướng dẫn! – Ana