2010-02-22 6 views
11

कोड के इस विशेष भाग का उद्देश्य को elems में सभी तत्वों की गणना करने से अधिक प्रभावी बनाना है। मैंने सूची बनाने वाले दो प्रकारों को संक्षेप में सुलझा लिया है, लेकिन मैं आकार फ़ंक्शन के हस्ताक्षर को प्रतीत नहीं कर सकता।आप "या तो ए" के प्रकार से कैसे मेल खाते हैं?

instance (Finite a, Finite b) => Finite (Either a b) where 
    elems = combineLists [Left x | x <- elems] [Right x | x <-elems] 
    size ??? = (size a) + (size b) 

प्रीलूड से, हम जानते हैं कि Either a b = Left a | Right b

पहली बात मैंने कोशिश की थी Either से मेल खाना था, लेकिन निश्चित रूप से यह एक प्रकार है, इसलिए यह काम नहीं करता है। इसके बाद, मैंने ((Left a) | (Right b)) की कोशिश की, लेकिन उस पर कोई भी नहीं। Either a b टाइप करने के लिए कुछ और नहीं लगता है।

मैं संकलित करने के लिए size (Left a) प्राप्त करने में सक्षम था, लेकिन बाद से यह b घटक गुम है, तो मैं त्रुटि प्राप्त:

Ambiguous type variable `b' in the constraint: 
    `Finite b' arising from a use of `size' at <interactive>:1:0-12 

जो पाठ्यक्रम के संदर्भ में समझ में आता है, लेकिन मैं वास्तव में कोई सुराग नहीं कैसे करने के लिए है मैच Either a b

किसी के पास कोई विचार है?

+1

आप एक प्रकार और एक कन्स्ट्रक्टर के बीच के अंतर के बारे में थोड़ा उलझन में लगते हैं। "या तो एक बी" एक प्रकार है जिसमें दो रचनाकार, "बाएं" और "दाएं" हैं। प्रकार प्रकार हस्ताक्षर में जाते हैं, जबकि रचनाकार कोड में जाते हैं। यह एक आम भ्रम है क्योंकि बहुत से प्रकार टाइप और कन्स्ट्रक्टर के लिए समान नाम का उपयोग करते हैं, जैसा कि "डेटा Foo = Foo Int String" में है; पहला "फू" प्रकार है, जबकि दूसरा कन्स्ट्रक्टर है। –

उत्तर

25

प्रकार Either a b की कुछ या तो एक Left a या एक Right b है, तो आप दो मामलों है कि अलग से नियंत्रित किया जा सकता है:

size (Left x) = size x 
size (Right x) = size x 

अस्पष्ट प्रकार चर के बारे में त्रुटि एक अलग मुद्दा है। यदि आप दुभाषिया में size (Left 1) जैसे कुछ टाइप करते हैं, तो सिस्टम Left 1 मान का "दायां" प्रकार क्या नहीं ले सकता है। यह Either Int anything हो सकता है और जब तक यह ज्ञात नहीं है कि anything किस प्रकार है, तो यह Finite (जो size द्वारा आवश्यक है) में चेक नहीं किया जा सकता है।

आप एक स्पष्ट प्रकार हस्ताक्षर निर्दिष्ट करने के द्वारा कि समस्या से बचने कर सकते हैं:

size (Left 1 :: Either Int String) 
0

मुसीबत होने के लिए है कि आप size के लिए एक डमी तर्क की जरूरत है लगता है, लेकिन आप दोनों प्रकार a और b के लिए dummies के पारित नहीं हो सकता एक Either a b में। शायद आप प्रत्येक प्रकार के एक डमी पाने के लिए elems उपयोग कर सकते हैं:

size _ = (size . head) (elems :: [a]) + (size . head) (elems :: [b]) 
0

मुझे लगता है कि मुख्य मुद्दा आप कर रहे हैं यह है कि आप एक प्रकार है कि एक ही समय में दो अन्य प्रकार से प्रत्येक से एक गृहीत का प्रतिनिधित्व करता है चाहता हूँ। Either a b देय समय पर केवल a या b में से एक हो सकता है।

एक साधारण डेटा प्रकार जो a और b दोनों का प्रतिनिधित्व करता है, एक ही समय में 2-टुपल होता है।ऐसी बात के लिए प्रकार हस्ताक्षर (a, b) है, जो भी एक बनाने के लिए अभिव्यक्ति है, और इसलिए पैटर्न एक मशीन:

> :type (4,5) 
(4,5) :: (Num t, Num t1) => (t, t1) 
> let f (a, b) = 2*a + b 
> f (4,5) 
13 

तुम इतनी तरह एक 2-टपल के साथ अपना पहला लाइन लेखन, विचार करना चाहिए:

instance (Finite a, Finite b) => Finite (a, b) where 

यह Finite (a, b) का प्रतिनिधित्व करता है? सदस्य कार्य परिभाषा क्या होगी?

+0

असल में मैंने पहले ही इसकी परिभाषा लिखी है, यह ए और बी का उत्पाद है, सभी बी के सभी के मैपिंग का निर्माण – Fry

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