2011-03-22 17 views
15

में किसी प्रकार की श्रेणी में उदाहरणों की एक सूची प्राप्त करें क्या प्रोग्राम प्रकार के प्रकार के उदाहरणों की सूची प्राप्त करने का कोई तरीका है?हास्केल

यह मुझे मारता है कि संकलक को कोड को जांचने और संकलित करने के लिए इस जानकारी को जानना चाहिए, तो कंपाइलर को बताने का कोई तरीका है: अरे, आप उस वर्ग के उन उदाहरणों को जानते हैं, कृपया उनकी एक सूची दें ठीक है (तारों के रूप में या जो भी उनमें से कुछ प्रतिनिधित्व)।

+0

दरअसल, संकलक नहीं जानता कि कौन से उदाहरण परिभाषित किए गए हैं। एकमात्र चीज यह कर सकती है, यह जांच कर रही है कि एक प्रकार टाइपक्लास का उदाहरण है या नहीं। – fuz

उत्तर

12

आप टेम्पलेट हास्केल का उपयोग करके दिए गए प्रकार के वर्ग के लिए दायरे में उदाहरण उत्पन्न कर सकते हैं।

import Language.Haskell.TH 

-- get a list of instances 
getInstances :: Name -> Q [ClassInstance] 
getInstances typ = do 
    ClassI _ instances <- reify typ 
    return instances 

-- convert the list of instances into an Exp so they can be displayed in GHCi 
showInstances :: Name -> Q Exp 
showInstances typ = do 
    ins <- getInstances typ 
    return . LitE . stringL $ show ins 

GHCi में यह चल रहा है:

*Main> $(showInstances ''Num) 
"[ClassInstance {ci_dfun = GHC.Num.$fNumInteger, ci_tvs = [], ci_cxt = [], ci_cls = GHC.Num.Num, ci_tys = [ConT GHC.Integer.Type.Integer]},ClassInstance {ci_dfun = GHC.Num.$fNumInt, ci_tvs = [], ci_cxt = [], ci_cls = GHC.Num.Num, ci_tys = [ConT GHC.Types.Int]},ClassInstance {ci_dfun = GHC.Float.$fNumFloat, ci_tvs = [], ci_cxt = [], ci_cls = GHC.Num.Num, ci_tys = [ConT GHC.Types.Float]},ClassInstance {ci_dfun = GHC.Float.$fNumDouble, ci_tvs = [], ci_cxt = [], ci_cls = GHC.Num.Num, ci_tys = [ConT GHC.Types.Double]}]" 

एक और उपयोगी तकनीक एक दिया प्रकार GHCi का उपयोग कर वर्ग के लिए दायरे में सभी उदाहरणों दिखा रहा है।

Prelude> :info Num 
class (Eq a, Show a) => Num a where 
    (+) :: a -> a -> a 
    (*) :: a -> a -> a 
    (-) :: a -> a -> a 
    negate :: a -> a 
    abs :: a -> a 
    signum :: a -> a 
    fromInteger :: Integer -> a 
    -- Defined in GHC.Num 
instance Num Integer -- Defined in GHC.Num 
instance Num Int -- Defined in GHC.Num 
instance Num Float -- Defined in GHC.Float 
instance Num Double -- Defined in GHC.Float 

संपादित करें: पता करने के लिए महत्वपूर्ण बात यह है (या GHCi शीघ्र, आदि में) है कि संकलक किसी भी मॉड्यूल में दायरे में प्रकार वर्गों में से केवल बारे में पता है। इसलिए यदि आप showInstances TH फ़ंक्शन को बिना किसी आयात के कहते हैं, तो आपको केवल प्रीलूड से उदाहरण मिलेंगे। यदि आपके पास दायरे में अन्य मॉड्यूल हैं, उदा। Data.Word, तो आप उन सभी उदाहरणों को भी देखेंगे।

+1

ऐसा लगता है कि यह केवल जीएचसी 7 और TH 2.5 के लिए काम करता है। TH 2.4.0.1 में ऐसा करने का प्रयास करने से मुझे वह नहीं लगता है जो मैं चाहता हूं। क्या यह एक नई सुविधा है? – mentics

+0

मैं जीएचसी 7.6.3 चला रहा हूं। यहां उत्तर का एक अपडेट दिया गया है: '[क्लास इंस्टेंस] 'अब' [InstanceDec] 'है। इसके अलावा, मुझे उदाहरण को डुप्लिकेट करने के लिए जीएचसीआई में 'सेट -XTemplateHaskell' चलाने की आवश्यकता है। – apolune

2

मुझे लगता है, यह संभव नहीं है। मैं आपको टाइपक्लास (जीएचसी के लिए) के कार्यान्वयन की व्याख्या करता हूं, इससे आप देख सकते हैं कि कंपाइलर को यह जानने की आवश्यकता नहीं है कि किस प्रकार टाइपक्लास का उदाहरण है। इसे केवल यह जानना है कि क्या एक विशिष्ट प्रकार उदाहरण है या नहीं।

एक टाइपक्लास का डेटाटाइप में अनुवाद किया जाएगा। ,

class Eq a where 
    (==),(/=) :: a -> a -> Bool 

typeclass शब्दकोश का एक प्रकार में अनुवाद किया जाएगा अपने सभी कार्यों युक्त: उदाहरण के लिए, के Eq ले जाने

data Eq a = Eq { 
    (==) :: a -> a -> Bool, 
    (/=) :: a -> a -> Bool 
    } 

प्रत्येक typeclass बाधा तो युक्त एक अतिरिक्त बहस में अनुवाद किया है शब्दकोश:

elem :: Eq a => a -> [a] -> Bool 
elem _ [] = False 
elem a (x:xs) | x == a = True 
       | otherwise = elem a xs 

हो जाता है:

elem :: Eq a -> a -> [a] -> Bool 
elem _ _ [] = False 
elem eq a (x:xs) | (==) eq x a = True 
       | otherwise = elem eq a xs 

महत्वपूर्ण बात यह है कि शब्दकोश रनटाइम पर पारित किया जाएगा। कल्पना कीजिए, आपकी परियोजना में कई मॉड्यूल हैं। जीएचसी को उदाहरणों के लिए सभी मॉड्यूल की जांच करने की ज़रूरत नहीं है, इसे सिर्फ देखना है, चाहे कोई उदाहरण कहीं भी परिभाषित किया गया हो।

लेकिन यदि आपके पास स्रोत उपलब्ध है, तो मुझे लगता है कि उदाहरण के लिए पुरानी शैली grep पर्याप्त होगी।

+1

बिल्कुल सही नहीं है। कंपाइलर को केवल यह जानने की जरूरत है कि कोई विशिष्ट प्रकार एक उदाहरण है, हालांकि किसी भी समय संकलक सभी मामलों को गुंजाइश में समझा सकता है और वांछित सूची उत्पन्न कर सकता है। यदि आप उदाहरण के लिए ': जानकारी संख्या' का उपयोग करते हैं तो जीएचसीआई ऐसा करेगा। –

0

मौजूदा कक्षाओं के लिए स्वचालित रूप से ऐसा करना संभव नहीं है। अपनी खुद की कक्षा और इसके उदाहरणों के लिए आप इसे कर सकते हैं। आपको टेम्पलेट हास्केल (या शायद अर्ध-उद्धरण) के माध्यम से सबकुछ घोषित करने की आवश्यकता होगी और यह स्वचालित रूप से कुछ अजीब डेटा संरचना उत्पन्न करेगा जो घोषित उदाहरणों को एन्कोड करता है। अजीब डेटा संरचना को परिभाषित करना और टेम्पलेट हास्केल बनाना यह विवरण है जिनके लिए उनके लिए उपयोग केस है।

शायद आप अपने निर्माण में कुछ टेम्पलेट हास्केल या अन्य जादू जोड़ सकते हैं ताकि सभी स्रोत फ़ाइलों को रन-टाइम (सी.एफ. प्रोग्राम क्विन) पर उपलब्ध पाठ के रूप में शामिल किया जा सके। फिर अपने कार्यक्रम 'ही grep' हैं ...

6

यह समस्याओं का एक बहुत में जैसे ही चलाने के लिए के रूप में आप

instance Eq a => Eq [a] where 
    [] == [] = True 
    (x:xs) == (y:ys) = x == y && xs == ys 
    _ == _ = False 

और

instance (Eq a,Eq b) => Eq (a,b) where 
    (a1,b1) == (a2,b2) = a1 == a2 && b1 == b2 

के साथ की तरह उदाहरण घोषणाओं पाने के लिए जा रहा है एक ठोस कंक्रीट उदाहरण (उदाहरण के लिए instance Eq Bool)। के रूप में ([((Bool,[Bool]),Bool)],Bool) और इसके आगे इन तरह के के विभिन्न संयोजनों के साथ साथ, Bool, [Bool], [[Bool]], [[[Bool]]] और इतने पर, (Bool,Bool), ((Bool,Bool),Bool), (((Bool,Bool),Bool),Bool) आदि -

आप Eq के लिए उदाहरणों की असीमित सूची मिल जाएगा।यह स्पष्ट नहीं है कि String में इन्हें कैसे प्रस्तुत किया जाए; यहां तक ​​कि TypeRep की एक सूची में कुछ सुंदर स्मार्ट गणना की आवश्यकता होगी।

संकलक (करने की कोशिश) कर सकते हैं अनुमान एक प्रकार किसी भी प्रकार के लिए Eq का एक उदाहरण है कि क्या है, लेकिन यह दायरे में स्थित सभी उदाहरण घोषणाओं में नहीं पढ़ता और फिर बस सभी संभव उदाहरणों बात का अनुमान लगाना शुरू होता है, के बाद से वह कभी खत्म नहीं होगा!

महत्वपूर्ण सवाल यह है कि आपको इसके लिए क्या चाहिए?

7

टेम्पलेट Haskell दस्तावेज़ देखें: http://hackage.haskell.org/packages/archive/template-haskell/2.5.0.0/doc/html/Language-Haskell-TH.html

reify का उपयोग करके आप एक जानकारी रिकॉर्ड है, जो एक वर्ग के लिए उदाहरणों की अपनी सूची में शामिल हो सकता है। आप isClassInstance और classInstances का भी उपयोग कर सकते हैं।