मैं सख्ती टूटा समाधान से असहमत करना चाहते हैं अब तक बनी हुयी थी।
instance MyClass a => Show a where
show a = myShow a
तरीके के कारण उदाहरण के संकल्प से काम करता है कि करने के लिए
, इस के आसपास चल रहा है के लिए एक बहुत ही खतरनाक उदाहरण है!
इंस्टेंस रिज़ॉल्यूशन प्रत्येक उदाहरण के =>
के दाएं हाथ की ओर से प्रभावी रूप से मिलान पैटर्न से प्राप्त होता है, पूरी तरह से =>
के बाईं ओर क्या है इसके संबंध में।
जब इनमें से कोई भी उदाहरण ओवरलैप नहीं होता है, तो यह एक सुंदर चीज़ है। हालांकि, आप यहां क्या कह रहे हैं "यहां एक नियम है जिसका उपयोग आपको के लिए उपयोग करना चाहिए उदाहरण दिखाएं। किसी भी प्रकार के शो शो के लिए पूछे जाने पर, आपको MyClass का एक उदाहरण चाहिए, इसलिए इसे प्राप्त करें, और यहां है कार्यान्वयन।" - एक बार जब कंपाइलर ने आपके उदाहरण का उपयोग करने के विकल्प के प्रति प्रतिबद्ध किया है, (केवल इस तथ्य के आधार पर कि 'ए' सब कुछ के साथ एकजुट हो) तो उसे वापस गिरने और किसी अन्य उदाहरण का उपयोग करने का कोई मौका नहीं है!
यदि आप इसे संकलित करने के लिए {-# LANGUAGE OverlappingInstances, IncoherentInstances #-}
इत्यादि चालू करते हैं, तो आप मॉड्यूल को लिखने वाले मॉड्यूल को लिखने के लिए जाते हैं जो इस परिभाषा को प्रदान करते हैं और किसी अन्य शो उदाहरण का उपयोग करने की आवश्यकता होती है। आखिरकार आप इस कोड को पर्याप्त एक्सटेंशन के साथ संकलित करने में सक्षम होंगे, लेकिन दुख की बात यह नहीं होगी कि आपको क्या करना चाहिए!
आपको दिया इसके बारे में सोचते हैं:
instance MyClass a => Show a where
show = myShow
instance HisClass a => Show a where
show = hisShow
जो संकलक लेने चाहिए?
आपका मॉड्यूल केवल इनमें से एक को परिभाषित कर सकता है, लेकिन अंतिम उपयोगकर्ता कोड मॉड्यूल का एक गुच्छा आयात करेगा, न केवल आपके।इसके अलावा, एक और मॉड्यूल को परिभाषित करता है, तो
instance Show HisDataTypeThatHasNeverHeardOfMyClass
संकलक उसके उदाहरण पर ध्यान न दें और तुम्हारा इस्तेमाल करने की कोशिश करने के लिए अपने अधिकार के भीतर अच्छी तरह से किया जाएगा।
सही जवाब, दुख की बात है, दो चीजें करना है।
प्रत्येक व्यक्ति MyClass के कहने तुम बहुत यांत्रिक परिभाषा
instance MyClass Foo where ...
instance Show Foo where
show = myShow
यह काफी दुर्भाग्यपूर्ण है, लेकिन अच्छी तरह से काम करता है जब वहाँ MyClass के बहुत कम उदाहरण तहत कर रहे हैं के साथ शो की एक इसी उदाहरण परिभाषित कर सकते हैं के लिए विचार।
जब आपके पास बड़ी संख्या में उदाहरण हैं, तो कोड-डुप्लिकेशन से बचने का तरीका (जब वर्ग शो से काफी जटिल है) परिभाषित करना है।
newtype WrappedMyClass a = WrapMyClass { unwrapMyClass :: a }
instance MyClass a => Show (WrappedMyClass a) where
show (WrapMyClass a) = myShow a
यह उदाहरण प्रेषण के लिए वाहन के रूप में नया प्रकार प्रदान करता है। और फिर
instance Foo a => Show (WrappedFoo a) where ...
instance Bar a => Show (WrappedBar a) where ...
, स्पष्ट है, क्योंकि WrappedFoo a
और WrappedBar a
के लिए प्रकार 'पैटर्न' संबंध तोड़ना है।
base
पैकेज में इस मुहावरे के कई उदाहरण चल रहे हैं।
नियंत्रण में। इस कारण से WrappedMonad
और WrappedArrow
के लिए परिभाषाएं हैं।
आदर्श रूप में आप कहते हैं कि करने में सक्षम हो जाएगा:
instance Monad t => Applicative t where
pure = return
(<*>) = ap
लेकिन प्रभावी रूप से क्या इस उदाहरण कह रही है कि हर अनुप्रयोगी पहले इकाई के लिए एक उदाहरण खोजने, और फिर इसे करने के लिए भेजने द्वारा प्राप्त किया जाना चाहिए। तो जब यह कहने का इरादा होगा कि हर मोनाड आवेदक है (जिस तरह से इम्प्रिकेशन-जैसे =>
पढ़ता है) वास्तव में यह कहता है कि प्रत्येक आवेदक एक मोनाड है, क्योंकि एक उदाहरण सिर 'टी' किसी भी प्रकार से मेल खाता है। कई मायनों में, 'इंस्टेंस' और 'क्लास' परिभाषाओं के लिए वाक्यविन्यास पीछे की तरफ है।
एफवाईआई मैंने इस प्रश्न को फिर से सुना क्योंकि यह अभी तक संक्षिप्त, स्पष्ट और अच्छी तरह से गठित है। एक मॉडल सवाल, और यदि संभव हो तो मैं इसे फिर से पढ़ूंगा। –