/ / हास्केल में एक प्रकार के वर्ग में उदाहरणों की एक सूची प्राप्त करें - हैस्केल, आत्मनिरीक्षण

हास्केल - हैकसेल, आत्मनिरीक्षण में एक प्रकार की कक्षा में उदाहरणों की एक सूची प्राप्त करें

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

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

उत्तर:

उत्तर № 1 के लिए 13

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

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

जीएचसीआई में यह चल रहा है:

*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]}]"

एक अन्य उपयोगी तकनीक जीएचसीआई का उपयोग करके किसी दिए गए प्रकार वर्ग के लिए सभी उदाहरणों को दिखा रही है।

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 बिना किसी आयात के साथ कार्य करें, आप केवल प्रस्तावना से उदाहरण प्राप्त कर सकते हैं। यदि आपके पास अन्य मॉड्यूल हैं, उदाहरण के लिए, Data.Word, तो आप उन सभी उदाहरणों को भी देखेंगे।


उत्तर के लिए 7 № 2

टेम्प्लेट में हैस्केल प्रलेखन देखें: http://hackage.haskell.org/packages/archive/template-haskell/2.5.0.0/doc/html/Language-Haskell-TH.html

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


जवाब के लिए 6 № 3

जैसे ही आपको उदघोषणाएं मिलती हैं, यह बहुत सारी समस्याओं में चला जाता है

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)।

आप "के लिए उदाहरणों की एक अनंत सूची प्राप्त करेंगे Eq - Bool,[Bool],[[Bool]],[[[Bool]]] और इसी तरह, (Bool,Bool), ((Bool,Bool),Bool), (((Bool,Bool),Bool),Bool) वगैरह, साथ ही इन के विभिन्न संयोजनों जैसे ([((Bool,[Bool]),Bool)],Bool) इत्यादि। यह स्पष्ट नहीं है कि इन का प्रतिनिधित्व कैसे किया जाए String; की एक सूची भी TypeRep कुछ सुंदर स्मार्ट गणना की आवश्यकता होगी।

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

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


जवाब के लिए 2 № 4

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

एक टाइपकास्ट का अनुवाद एक डेटाटाइप में किया जाएगा। एक उदाहरण के रूप में, चलो लेते हैं Eq:

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

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

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

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

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

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

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


जवाब के लिए 0 № 5

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

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