2011-12-30 18 views
8

recent exchange के आधार पर, मुझे संकलन-समय प्रकार की सुरक्षा सुनिश्चित करने के लिए कुछ कोड उत्पन्न करने के लिए टेम्पलेट हास्केल का उपयोग करने के लिए आश्वस्त किया गया है।हास्केल रिकॉर्ड के फील्ड नामों और प्रकारों का आत्मनिरीक्षण

मुझे रिकॉर्ड फ़ील्ड नामों और प्रकारों का आत्मनिरीक्षण करने की आवश्यकता है। मैं समझता हूं कि constrFields . toConstr :: Data a => a -> [String] का उपयोग करके मैं get field names कर सकता हूं। लेकिन मुझे फील्ड नामों से अधिक की जरूरत है, मुझे उनके प्रकार को जानने की जरूरत है। उदाहरण के लिए, मुझे Bool प्रकार वाले फ़ील्ड के नामों को जानने की आवश्यकता है।

मैं एक समारोह f :: a -> [(String, xx)] जहां a रिकॉर्ड है कैसे निर्माण करते हैं, String क्षेत्र का नाम है और xx फ़ील्ड प्रकार है?

उत्तर

8

Inforeify द्वारा प्रदान किए गए मूल्य में, अन्य सभी चीज़ों के साथ, प्रकार उपलब्ध होना चाहिए। विशेष रूप से, आपको TyConI प्राप्त करना चाहिए, जिसमें a Dec value शामिल है, जिससे आप Con values specifying the constructors की सूची प्राप्त कर सकते हैं। एक रिकॉर्ड प्रकार को RecC का उपयोग करना चाहिए, जो आपको फ़ील्ड का नाम described by a tuple फ़ील्ड नाम, चाहे फ़ील्ड सख्त हो, और the type फ़ील्ड का एक सूची देगा।

आप वहां से कहां जाते हैं इस पर निर्भर करता है कि आप इन सब के साथ क्या करना चाहते हैं।


संपादित:

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")])] है।

क्या इससे आपको कोई अंदाजा नहीं लगता है?

+0

यही वही है जो मैं ढूंढ रहा हूं। मैंने आपका उदाहरण निम्नलिखित पर उबाल दिया: 'introspect n = reify n >> = stringE। show'। मार्गदर्शन के लिए धन्यवाद! – Ana

संबंधित मुद्दे