2011-12-17 29 views
6

पर आवृत्ति घोषणा से उदाहरण के लिए हास्केल प्रकार संदर्भ, मैंने बनाए गए डेटा प्रकार के लिए एक उदाहरण घोषणा करने में एक प्रकार का संदर्भ उपयोग किया।फ़ंक्शन

data Set a = Insert a (Set a) | EmptySet 

instance (Show a) => Show (Set a) where 
    show x = "{" ++ show' x ++ "}" where 
     show' (Insert x EmptySet) = show x 
     show' (Insert x xs) = show x ++ ", " ++ show' xs 

instance Eq a => Eq (Set a) where 
    (Insert x xs) == (Insert y ys) = (x == y) && (xs == ys) 

तो अब, मैं कार्यों मुझे लगता है कि मेरी सेट प्रकार का उपयोग करें, तो तरह परिभाषित सभी के लिए समीकरण प्रकार प्रसंग जोड़ने के लिए है, या मैं एक प्रकार त्रुटि मिलती है:

memberSet::Eq a =>a->Set a->Bool 
memberSet _ EmptySet = False 
memberSet x (Insert y ys) 
    | x == y = True 
    | otherwise = memberSet x ys 

subSet::Eq a=>Set a->Set a->Bool 
subSet EmptySet _ = True 
subSet (Insert a as) bs 
    | memberSet a bs = subSet as bs 
    | otherwise = False 

त्रुटि मुझे लगता है:

No instance for (Eq a) 
     arising from a use of `==' 
    In the expression: (x == y) 
    In a stmt of a pattern guard for 
       an equation for `memberSet': 
     (x == y) 
    In an equation for `memberSet': 
     memberSet x (Insert y ys) 
      | (x == y) = True 
      | otherwise = memberSet x ys 
Failed, modules loaded: none. 

इसका क्या अर्थ है? मुझे यह त्रुटि क्यों मिलती है? मैंने सोचा कि एक बार जब मैंने घोषणा की घोषणा की, तो हास्केल स्वचालित रूप से यह सत्यापित करने में सक्षम होगा कि मेरे कार्यों में "==" की तुलना में चीजों की तुलना "सदस्यसेट" और "सबसेट" स्वचालित रूप से "ईक" के उदाहरणों के लिए की जाएगी। स्पष्टता के लिए

संपादित करें:

मेरे मुद्दा यह है कि मुझे समझ नहीं आता क्यों प्रकार संदर्भों "memberSet" और पर आवश्यक हैं कि "सबसेट।" अगर मैं उन्हें इस तरह हटा देता हूं, तो यह संकलित नहीं होता है।

memberSet::a->Set a->Bool 
    memberSet _ EmptySet = False 
    memberSet x (Insert y ys) 
     | x == y = True 
     | otherwise = memberSet x ys 

    subSet::Set a->Set a->Bool 
    subSet EmptySet _ = True 
    subSet (Insert a as) bs 
     | memberSet a bs = subSet as bs 
     | otherwise = False 
+0

वह कोड जो आप मेरे लिए टाइप चेक देते हैं।तुम क्या छोड़ रहे हो – bdonlan

+0

मुझे किसी प्रकार की काफी सूक्ष्म त्रुटि का संदेह है जो दायरे या नाम शामिल है, क्योंकि दिया गया कोड ठीक लगता है। –

+0

मेरा प्रश्न अस्पष्ट था। कोड संकलित है। मैं सोच रहा हूं कि यह "सदस्यसेट" और "सबसेट" पर प्रकार के संदर्भ के साथ संकलित क्यों नहीं करेगा, मैं संपादित करूंगा। –

उत्तर

4

क्या आपके उदाहरण घोषणा का कहना है कि Set aEq का एक उदाहरण है जब भी a है। चाहे a है, वास्तव में, Eq का एक उदाहरण पूरी तरह से एक और मामला है; यह आपको केवल == के साथ Set एस की तुलना करने की अनुमति देता है, जबकि memberSet में आप केवल तत्वों की तुलना कर रहे हैं।

Integer -> Integer टाइप करें। यह उन कारणों के लिए Eq का उदाहरण नहीं है जो स्पष्ट होना चाहिए। Set में उस प्रकार के तत्व शामिल हैं तो आप memberSet पर काम करने के लिए कैसे उम्मीद करेंगे?

मुझे आश्चर्य है अगर आप क्या यहाँ पूरा करने के लिए उम्मीद कर रहे थे एक तत्व प्रकार Eq का एक उदाहरण बनाया जा सकता है है कि के साथ यह सुनिश्चित करना है कि केवल Set रों। यदि ऐसा है, तो यह एक बहुत ही अलग समस्या है, लेकिन अधिकतर अनावश्यक - Set एस का उपयोग करके फ़ंक्शंस पर बाधा को छोड़कर अंत में एक ही उद्देश्य प्रदान करता है।

the standard Data.Set module पर नज़र डालें क्यों? ध्यान दें कि सेट पर चलने वाले अधिकांश कार्यों में Ord बाधा है, इस तथ्य को दर्शाते हुए कि आंतरिक प्रतिनिधित्व एक बाइनरी खोज पेड़ है।

+0

धन्यवाद। मैं बस हास्केल के साथ खुद को परिचित करने की कोशिश कर रहा था। मैंने बस एसआईसीपी से कार्यान्वयन का मोटे तौर पर अनुवाद किया। मैं विशेष रूप से कुछ भी हासिल करने की कोशिश नहीं कर रहा था। मैंने थोड़ी सी कोड भी छोड़ी, मैं समानता के लिए सेट की तुलना करने में सक्षम होना चाहता था। यही कारण है कि यह ईक का एक उदाहरण है। ऐसा करने के लिए, मुझे लगता है कि सभी को ईक –

+0

@ जोश का उदाहरण होना था: ठीक है तो आप भाग्य में हैं, क्योंकि अब आप आधिकारिक तौर पर कक्षा की बाधाओं के प्रकार के बारे में अधिक परिचित हैं। :] और हां, दो सेटों की तुलना करने के लिए अपने तत्वों की तुलना करने की आवश्यकता है, इसलिए आप उस हिस्से के बारे में सही हैं। –

7

बस के लिए यह मजाक है, आप इसे की व्यवस्था कर सकते हैं, जिससे कि कमी एक GADT का उपयोग करके कार्यों पर आवश्यक नहीं हैं:

{-# LANGUAGE GADTs #-} 
module Set where 

data Set x where 
    EmptySet :: Set a 
    Insert :: Eq a => a -> Set a -> Set a 

instance Show a => Show (Set a) where 
    show EmptySet = "{}" 
    show xs = "{" ++ show' xs ++ "}" 
     where 
     show' (Insert a EmptySet) = show a 
     show' (Insert a ys) = show a ++ ", " ++ show' ys 

instance Eq (Set a) where 
    (Insert x xs) == (Insert y ys) = x == y && xs == ys 
    EmptySet == EmptySet = True 
    _ == _ = False 

memberSet :: a -> Set a -> Bool 
memberSet x (Insert y ys) = x == y || memberSet x ys 
memberSet _ _ = False 

subSet :: Set a -> Set a -> Bool 
subSet EmptySet _ = True 
subSet (Insert a as) bs 
    | memberSet a bs = subSet as bs 
    | otherwise = False 

प्रकार के Insert निर्माता पर Eq बाधा डाल करके , हम यह सुनिश्चित कर सकते हैं कि

  1. नहीं अरिक्त समुच्च्य Eq में नहीं प्रकार के लिए निर्माण किया जा सकता।
  2. Eq संदर्भ (और शब्दकोश) जब भी हम Insert कन्स्ट्रक्टर पर पैटर्न-मिलान उपलब्ध होते हैं, तो हमें फ़ंक्शन के प्रकार हस्ताक्षर में इसका उल्लेख करने की आवश्यकता नहीं है।
+0

वाह, मुझे नहीं पता था कि आप ऐसा कर सकते हैं ... तो, क्या मुझे ऐसा करने पर टाइप कन्स्ट्रक्टर घोषित करने की ज़रूरत नहीं है? –

+0

क्या आपका मतलब है '' टाइपर्स कन्स्ट्रक्टर 'के बजाय,' मुझे टाइप क्लास घोषित करने की ज़रूरत नहीं है '? यदि ऐसा है, तो उस निर्माता पर पैटर्न-मिलान होने पर आपके द्वारा 'GADT' में मान कन्स्ट्रक्टर पर रखी गई बाधाएं उपलब्ध हैं, इसलिए उन्हें फ़ंक्शन के प्रकार हस्ताक्षर में दोहराया जाना आवश्यक नहीं है। हस्ताक्षर में अन्य बाधाओं को निश्चित रूप से दिया जाना चाहिए। हालांकि, ध्यान रखें कि संदर्भ केवल _pattern मिलान_ पर उपलब्ध है, हर जगह नहीं जहां आप प्रकार के मानों का उपयोग करते हैं। –

+0

@ जोश: यदि आप 'इन्टरर्ट' और 'एम्प्टीसेट' जैसे डेटा कन्स्ट्रक्टर के बारे में सोच रहे हैं, तो वे अभी भी वहां हैं। यह उन्हें परिभाषित करने के लिए सिर्फ एक वैकल्पिक वाक्यविन्यास है। –