2012-09-09 19 views
6

में डेटा प्रकारों का उपयोग करके मैंने इसे एक नया प्रश्न शुरू कर दिया है क्योंकि यह मेरे पिछले प्रश्न से फॉलो-ऑन बन गया है।हास्केल

अगर मैं जो समान कंस्ट्रक्टर्स का बना रहे हैं दो डेटा प्रकार है:

data A = C | Z 
data B = C 

data C = X | Y 

अगर आप देख सकते हैं कि मैं क्या कर रहा हूँ:

data A = X | Y | Z 
data B = X | Y 

कोई रास्ता नहीं मैं किसी भी तरह इस का प्रतिनिधित्व कर सकते है - मैं एक्स को समूहबद्ध करने की कोशिश कर रहा हूं वाई एक डेटा प्रकार में, जिसे कई अन्य डेटा प्रकारों द्वारा उपयोग किया जा सकता है। मुझे यह अनुमति देने के लिए कंपाइलर नहीं मिल रहा है, या यदि ऐसा होता है, तो मैं एक्स या वाई के खिलाफ पैटर्न-मिलान नहीं कर सकता, केवल सी ??

मुझे त्रुटि संदेश मिलता है कि सी को कई बार घोषित किया गया है।

मैंने सोचा कि मैं शायद प्रकार का उपयोग कर सकता हूं, लेकिन वे कई टाइपिंग की अनुमति नहीं देते हैं।

संपादित

यहां तक ​​कि अगर मैं लंबा रास्ता तय की घोषणा (नीचे) की तरह, यह अभी भी संकलन नहीं है और कहते हैं एक्स और वाई कई घोषणाओं है:

data A = X | Y | Z 
data B = X | Y 
+0

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

+0

@ गिल्स: नहीं, हास्केल में कोई सबटाइप पॉलीमोर्फिज्म नहीं है। इसमें केवल पैरामीट्रिक पॉलिमॉर्फिज्म है, और टाइप-क्लास के माध्यम से एड-हाॉक पॉलिमॉर्फिज्म है। सबसे नज़दीकी चीज जो आप प्राप्त कर सकते हैं वह एक अस्तित्वहीन प्रकार है, लेकिन यह लगभग पूरी तरह से अलग है, लेकिन काफी नहीं है। –

+0

मैं इसे एक उत्तर के रूप में रखूंगा, लेकिन क्योंकि यह काफी नहीं है .. आप एक टाइपक्लास घोषित करके और फिर उन "सामान्य चीजों" के लिए आवश्यक संचालन के जरिए जो चाहते हैं उसके करीब पहुंच सकते हैं। इस समस्या को हल करने के लिए आसपास चीजों को फ़्लिप करने का यह एक बहुत ही आम तरीका है ( –

उत्तर

13

न केवल आप ऐसा नहीं कर सकते यह, आप अपना पहला विकल्प भी नहीं कर सकते - यानी आपके पास एक ही मॉड्यूल में दो प्रकार नहीं हो सकते हैं, दोनों में X और Y नामक रचनाकार हैं।

यदि आप ऐसा कर सकते हैं, तो X का प्रकार क्या होना चाहिए - C, A या B? सबसे स्पष्ट उत्तर C होगा, लेकिन फिर आप इसे संदर्भ में उपयोग नहीं कर पाएंगे जहां A या B आवश्यक हैं (ध्यान दें कि हास्केल में कोई सबटाइपिंग नहीं है), जिससे पूरे निर्माण के उद्देश्य को हराने में मदद मिलेगी।

data A = AC C | Z 
data B = BC C 
data C = X | Y 

तो आप के साथ एक सी लपेट सकता है या तो AC या BC निर्माता प्रकार का एक मान बनाने के लिए:

सबसे अच्छा तुम कर सकते हो

ए और बी के एक निर्माता में सी रैप करने के लिए अर्थात है A या B क्रमशः।

+0

बस यह कहने के लिए संपादित किया गया कि मेरा पहला विकल्प काम नहीं करता है। जब आप कहते हैं कि "लपेटें" का शाब्दिक अर्थ है "मूल सी से अलग करने के लिए सी के सामने वाक्यविन्यास का कुछ अन्य टुकड़ा शामिल करें"? – Lethi

+2

@ डैन हां। मेरे उदाहरण में, आप 'बी 'के मूल्य बनाने के लिए' ए' और' बीसी एक्स' प्रकार का मान बनाने के लिए 'एसी एक्स' लिखेंगे। अपने आप से 'एक्स' में दो अलग-अलग प्रकार नहीं हो सकते हैं। – sepp2k

4

कारण आप इस

data A = X | Y | Z 
data B = X | Y 

इस प्रकार है नहीं कर सकते।

foo n = (n,X) 

जो पहले स्लॉट और दूसरा स्लॉट में X में n से मिलकर एक जोड़ी बनाता है: आप बाद में कुछ कोड लिखने का कहना है। कंपाइलर का किस प्रकार का अनुमान लगाया जाना चाहिए? एक मान्य प्रकार

foo :: a -> A -> (a,A) 

होगा के बाद से X प्रकार A के एक निर्माता है, लेकिन समान रूप से मान्य

foo :: a -> B -> (a,B) 

है के बाद से X प्रकार B के एक निर्माता है।यदि आपके पास एक ही नाम के साथ दो रचनाकार हैं, तो आप उन कार्यों के लिए एक अद्वितीय प्रकार का अनुमान नहीं लगा सकते हैं जो उनका उपयोग करते हैं। तो आप एक ही मॉड्यूल में एक ही नाम में दो रचनाकार देने से वंचित हैं। (क्यों बिल्कुल B है एक अलग रूप में के रूप में, यदि Bसमान करने के लिए C है, तो?)

data A = C | Z 
data B = C 

data C = X | Y 

लेकिन क्या आप कर सकते हैं:

1

आप ऐसा नहीं कर सकते ऐसा कुछ करें:

data A = A_Other C | Z 
data B = B_Other C 

data C = X | Y 

फिर आप कर सकते हैं इस तरह पैटर्न मैच:

foo :: A -> String 
foo (A_Other X) = "X" 
foo (A_Other Y) = "Y" 
foo (  Z) = "Z" 

bar :: B -> String 
bar (B_Other X) = "X" 
bar (B_Other Y) = "Y" 

foobar :: C -> String 
foobar X = "X" 
foobar Y = "Y" 

कि समझ में आता है, तो ...

0

आप आप क्या चाहते हैं नहीं कर सकते क्योंकि आप एक से अधिक डेटा कंस्ट्रक्टर्स की घोषणा कर रहे हैं।

data A = X | Y | Z 

में आप वास्तव में प्रकार A जो 3 कंस्ट्रक्टर्स (मान) X, Y, और Z है शुरू कर रहे हैं। यही कारण है कि कोड का आपका पहला भाग संकलित नहीं होगा, यह दो अलग-अलग प्रकार के लिए कन्स्ट्रक्टर के रूप में सूचीबद्ध वही नाम देखता है! आप ऐसा कर सकता है, तो आप से पूछना चाहता खुद

X :: A 

या

X :: B 

जो एक गैर वस्तु उन्मुख संदर्भ में डरावना है होगा! इसलिए आपको अंतर्निहित डेटा, C साझा करने के लिए विभिन्न कन्स्ट्रक्टर नाम प्रदान करने की आवश्यकता है।

आप इस कारक चाहते हैं, आप के रूप में अन्य पदों का सुझाव दिया है और प्रत्येक डेटाप्रकार के लिए अद्वितीय कंस्ट्रक्टर्स कारक चुके डेटा है क्या कर सकते हैं

data A = CForA C | Z 
data B = CForB C 

data C = X | Y