हास्केल में अनाथ उदाहरण


86

-Wallविकल्प के साथ मेरे हास्केल एप्लिकेशन को संकलित करते समय, GHC अनाथ उदाहरणों के बारे में शिकायत करता है, उदाहरण के लिए:

Publisher.hs:45:9:
    Warning: orphan instance: instance ToSElem Result

प्रकार वर्ग ToSElemमेरा नहीं है, यह HStringTemplate द्वारा परिभाषित किया गया है

अब मुझे पता है कि इसे कैसे ठीक किया जाए (उदाहरण घोषणा में मॉड्यूल को स्थानांतरित करें जहां परिणाम घोषित किया गया है), और मुझे पता है कि जीएचसी अनाथ उदाहरणों से बचना क्यों पसंद करेंगे , लेकिन मैं अभी भी मानता हूं कि मेरा रास्ता बेहतर है। मुझे परवाह नहीं है अगर संकलक को असुविधा होती है - बल्कि मेरे मुकाबले।

ToSElemप्रकाशक मॉड्यूल में मैं अपने उदाहरणों को घोषित करना चाहता हूं , क्योंकि यह प्रकाशक मॉड्यूल है जो HStringTemplate पर निर्भर करता है, अन्य मॉड्यूल नहीं। मैं चिंताओं को अलग करने और हर मॉड्यूल HStringTemplate पर निर्भर होने से बचने की कोशिश कर रहा हूं।

मैंने सोचा कि हास्केल के प्रकार वर्गों के लाभों में से एक, जब जावा के इंटरफेस के उदाहरण के लिए तुलना की जाती है, तो यह है कि वे बंद होने के बजाय खुले हैं और इसलिए उदाहरणों को डेटा प्रकार के रूप में उसी स्थान पर घोषित नहीं करना पड़ता है। जीएचसी की सलाह इसे नजरअंदाज करने वाली लगती है।

इसलिए, जो मैं देख रहा हूं वह या तो कुछ मान्यता है कि मेरी सोच ध्वनि है और मैं इस चेतावनी को अनदेखा / दबाने, या चीजों को अपने तरीके से करने के खिलाफ अधिक ठोस तर्क में उचित होगा।


जवाब और टिप्पणियों में चर्चा दर्शाती है कि एक निष्पादन योग्य में अनाथ उदाहरणों को परिभाषित करने के बीच एक बड़ा अंतर है , जैसा कि आप कर रहे हैं, बनाम एक पुस्तकालय में जो दूसरों के संपर्क में है। यह जबरदस्त लोकप्रिय प्रश्न बताता है कि अनाथ उदाहरणों को भ्रमित करने वाले पुस्तकालय के अंतिम उपयोगकर्ताओं के लिए कैसे हो सकता है।
क्रिश्चियन कोंकले

जवाबों:


94

मैं समझता हूं कि आप ऐसा क्यों करना चाहते हैं, लेकिन दुर्भाग्य से, यह केवल एक भ्रम हो सकता है कि हास्केल कक्षाएं आपके कहने के तरीके में "खुली" लगती हैं। कई लोगों को लगता है कि ऐसा करने की संभावना हास्केल विनिर्देशन में एक बग है, जिन कारणों से मैं नीचे बताऊंगा। वैसे भी, यदि यह वास्तव में उदाहरण के लिए उपयुक्त नहीं है, तो आपको उस मॉड्यूल में घोषित किए जाने की आवश्यकता होती है जहां कक्षा घोषित की जाती है या मॉड्यूल में जहां प्रकार घोषित किया जाता है, वह संभवतः एक संकेत है कि आपको newtypeया किसी अन्य आवरण का उपयोग करना चाहिए। अपने प्रकार के आसपास।

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

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

इसका सबसे सरल प्रभाव यह है कि आपके पास एक पूरी तरह से काम करने वाला कार्यक्रम हो सकता है जो किसी अन्य व्यक्ति द्वारा आपके मॉड्यूल की दूर की निर्भरता में किए गए बदलाव के कारण अचानक संकलन करना बंद कर देगा।

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

जो लोग गारंटी चाहते हैं कि ये समस्याएं उनके साथ कभी नहीं होंगी, उन्हें इस नियम का पालन करना चाहिए कि यदि किसी ने, कहीं भी, कभी भी एक निश्चित प्रकार के लिए एक निश्चित वर्ग का उदाहरण घोषित किया है, तो किसी भी अन्य कार्यक्रम में किसी अन्य उदाहरण को फिर से घोषित नहीं किया जाना चाहिए। किसी से भी। बेशक, newtypeएक नया उदाहरण घोषित करने के लिए एक का उपयोग करने का समाधान है , लेकिन यह हमेशा कम से कम एक छोटी सी असुविधा है, और कभी-कभी एक प्रमुख है। इसलिए इस अर्थ में, जो लोग जानबूझकर अनाथ उदाहरण लिखते हैं, बल्कि उन्हें थोपा जा रहा है।

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

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

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

इस सब से मेरा निष्कर्ष यह है कि कम से कम समय के लिए, मैं दृढ़ता से सलाह दूंगा कि आप किसी भी अनाथ उदाहरण की घोषणा करने से बचें, यदि कोई अन्य कारण नहीं है तो दूसरों पर विचार करें। एक का उपयोग करें newtype


4
विशेष रूप से, यह पुस्तकालयों में वृद्धि के साथ एक समस्या है। हास्केल पर> 2200 पुस्तकालयों, और 10 हजार हजारों व्यक्तिगत मॉड्यूल के साथ, उदाहरण लेने का जोखिम नाटकीय रूप से बढ़ता है।
डॉन स्टीवर्ट

16
पुन: "मुझे लगता है कि सही समाधान हास्केल के आयात तंत्र में एक विस्तार जोड़ने के लिए होगा जो उदाहरणों के आयात को नियंत्रित करेगा" यदि यह विचार किसी को भी रुचता है, तो यह उदाहरण के लिए स्काला भाषा को देखने लायक हो सकता है; इसमें 'इम्पीचिट्स' के दायरे को नियंत्रित करने के लिए बहुत कुछ इस तरह से है, जिसे टाइपकास्ट इंस्टेंस की तरह इस्तेमाल किया जा सकता है।
मैट

5
मेरा सॉफ़्टवेयर एक लाइब्रेरी के बजाय एक एप्लिकेशन है, इसलिए अन्य डेवलपर्स के लिए समस्या पैदा करने की संभावना बहुत अधिक शून्य है। आप प्रकाशक मॉड्यूल को एक पुस्तकालय के रूप में आवेदन और बाकी मॉड्यूल पर विचार कर सकते हैं लेकिन अगर मैं पुस्तकालय को वितरित करने के लिए था तो यह प्रकाशक के बिना होगा और इसलिए, अनाथ उदाहरण हैं। लेकिन अगर मैंने अन्य मॉड्यूल में उदाहरणों को स्थानांतरित किया, तो लाइब्रेरी HStringTemplate पर एक अनावश्यक निर्भरता के साथ जहाज करेगी। तो इस मामले में मुझे लगता है कि अनाथ ठीक हैं, लेकिन अगर मैं एक ही समस्या को एक अलग संदर्भ में सामना करता हूं तो मैं आपकी सलाह पर ध्यान दूंगा।
डैन डायर

1
यह एक उचित दृष्टिकोण की तरह लगता है। उसके बाद देखने के लिए केवल एक चीज है जो आपके द्वारा आयात किए गए मॉड्यूल का लेखक इस उदाहरण को बाद के संस्करण में जोड़ता है। यदि वह उदाहरण आपके जैसा ही है, तो आपको अपनी स्वयं की उदाहरण घोषणा को हटाना होगा। यदि वह उदाहरण आपसे अलग है, तो आपको अपने प्रकार के चारों ओर एक नया टाइप रेपर लगाना होगा - जो आपके कोड का एक महत्वपूर्ण रिफैक्टिंग हो सकता है।
यित्ज़

@ मैट: वास्तव में, आश्चर्यजनक रूप से स्काला को यह एक अधिकार मिलता है जहाँ हास्केल नहीं करता है! (निश्चित रूप से स्काला में टाइप क्लास मशीनरी के लिए प्रथम श्रेणी के वाक्य-विन्यास का अभाव है, जो और भी बुरा है ...)
एरिक कपलुन

44

आगे बढ़ो और इस चेतावनी को दबाओ!

आप अच्छी कंपनी में हैं। कॉनल इसे "TypeCompose" में करता है। "chp-mtl" और "chp-transformers" इसे करते हैं, "control-monad-अपवाद-mtl" और "control-monad-अपवाद-monadsfd" इसे करते हैं, आदि।

btw आप शायद पहले से ही यह जानते हैं, लेकिन उन लोगों के लिए जो एक खोज पर आपके प्रश्न को रोक नहीं सकते हैं:

{-# OPTIONS_GHC -fno-warn-orphans #-}

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

मैं उन समस्याओं को स्वीकार करता हूं जो Yitz ने अपने जवाब में वास्तविक समस्याओं के रूप में उल्लेख किया है। हालाँकि, मैं अनाथ उदाहरणों को एक समस्या के रूप में भी उपयोग नहीं कर रहा हूं, और मैं "कम से कम सभी बुराइयों" को लेने की कोशिश करता हूं, जो अनाथ उदाहरणों का विवेकपूर्ण उपयोग करने के लिए है।

मैंने केवल अपने संक्षिप्त उत्तर में एक विस्मयादिबोधक-बिंदु का उपयोग किया है क्योंकि आपका प्रश्न दिखाता है कि आप पहले से ही समस्याओं से अच्छी तरह परिचित हैं। अन्यथा, मैं कम उत्साही होता :)

थोड़ा सा मोड़, लेकिन मेरा मानना ​​है कि समझौता किए बिना एक आदर्श दुनिया में सही समाधान है:

मेरा मानना ​​है कि समस्याओं का उल्लेख Yitz करता है (न जाने कौन सा उदाहरण उठाया गया है) एक "समग्र" प्रोग्रामिंग प्रणाली में हल किया जा सकता है:

  • आप केवल मुख्य रूप से पाठ फ़ाइलों को संपादित नहीं कर रहे हैं, बल्कि पर्यावरण द्वारा सहायता प्रदान कर रहे हैं (उदाहरण के लिए कोड पूरा होने पर केवल प्रासंगिक प्रकारों की बातों का सुझाव देते हैं)
  • "निचले स्तर" की भाषा में टाइप-कक्षाओं के लिए कोई विशेष समर्थन नहीं है, और इसके बजाय फ़ंक्शन तालिकाओं को स्पष्ट रूप से पास किया जाता है
  • लेकिन, "उच्च स्तर" प्रोग्रामिंग वातावरण कोड को इसी तरह से प्रदर्शित करता है कि हास्केल को अब कैसे प्रस्तुत किया जाता है (आप आमतौर पर फ़ंक्शन टेबल को पास नहीं देखेंगे), और स्पष्ट होने पर आपके लिए स्पष्ट प्रकार-वर्ग चुनता है (के लिए) उदाहरण फ़ंक्टर के सभी मामलों में केवल एक ही विकल्प होता है) और जब कई उदाहरण हों (सूची को लागू करना या सूची-मोनाद आवेदक, प्रथम / अंतिम / लिफ्ट शायद मोनॉयड) यह आपको यह चुनने की अनुमति देता है कि किस उदाहरण का उपयोग करना है।
  • किसी भी स्थिति में, तब भी जब उदाहरण आपके लिए स्वचालित रूप से उठाया गया था, तो वातावरण आपको आसानी से यह देखने की अनुमति देता है कि किस इंटरफ़ेस का उपयोग किया गया था, एक आसान इंटरफ़ेस (हाइपरलिंक या होवर इंटरफ़ेस या कुछ और) के साथ

काल्पनिक दुनिया से वापस (या भविष्य की उम्मीद), अभी: मैं सलाह देता हूं कि अनाथ वृत्ति से बचने की कोशिश करते हुए जब भी आप "वास्तव में" की आवश्यकता हो तो उनका उपयोग करें


5
हां, लेकिन यकीनन उनमें से प्रत्येक घटना किसी न किसी आदेश की गलती है। या तो मन के लिए नियंत्रण-मोनाड-अपवाद-एमटीएल और मोनाड्स-एफडी में बुरी घटनाएं। यह कम अप्रिय होगा उनमें से प्रत्येक मॉड्यूल को अपने स्वयं के प्रकारों को परिभाषित करने या न्यूटाइप रैपर की आपूर्ति करने के लिए मजबूर किया जाएगा। लगभग हर अनाथ उदाहरण एक सिरदर्द है जो होने की प्रतीक्षा कर रहा है, और यदि कुछ और नहीं तो यह सुनिश्चित करने के लिए आपके निरंतर सतर्कता की आवश्यकता होगी कि यह आयात किया गया है या उचित नहीं है।
एडवर्ड KMETT

2
धन्यवाद। मुझे लगता है कि मैं इस विशेष स्थिति में उनका उपयोग करूंगा, लेकिन Yitz के लिए धन्यवाद अब मुझे इस बात की बेहतर सराहना है कि वे किन समस्याओं का कारण बन सकते हैं।
डैन डायर

37

अनाथ उदाहरण एक उपद्रव है, लेकिन मेरी राय में वे कभी-कभी आवश्यक होते हैं। मैं अक्सर पुस्तकालयों को जोड़ता हूं जहां एक प्रकार एक पुस्तकालय से आता है और एक वर्ग दूसरे पुस्तकालय से आता है। बेशक, इन पुस्तकालयों के लेखकों से हर प्रकार और वर्गों के बोधगम्य संयोजन के लिए उदाहरण देने की उम्मीद नहीं की जा सकती है। इसलिए मुझे उन्हें प्रदान करना है, और इसलिए वे अनाथ हैं।

जिस विचार को आपको एक नए प्रकार में लपेटना चाहिए, जब आपको एक उदाहरण प्रदान करने की आवश्यकता होती है, तो सैद्धांतिक योग्यता के साथ एक विचार है, लेकिन यह कई परिस्थितियों में बहुत कठिन है; यह उस तरह का विचार है जो उन लोगों द्वारा आगे रखा जाता है जो जीवित रहने के लिए हास्केल कोड नहीं लिखते हैं। :)

तो आगे बढ़ो और अनाथ उदाहरण प्रदान करें। वे हानिरहित हैं।
यदि आप अनाथ उदाहरणों के साथ ghc को क्रैश कर सकते हैं तो यह एक बग है और इस तरह की रिपोर्ट की जानी चाहिए। (बग ghc के पास कई उदाहरणों का पता लगाने के बारे में नहीं है / जिन्हें ठीक करना मुश्किल नहीं है।)

लेकिन इस बात का ध्यान रखें कि भविष्य में कुछ समय के बाद कोई और उदाहरण आपके पास हो सकता है, और आपको एक (संकलन समय) त्रुटि मिल सकती है।


2
(Ord k, Arbitrary k, Arbitrary v) ⇒ Arbitrary (Map k v)QuickCheck का उपयोग करते समय एक अच्छा उदाहरण है ।
एरिक कपलुन

17

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

एक और अपवाद है - यदि आप न तो टाइपकास्ट या डेटा प्रकार के मालिक हैं, लेकिन एक बाइनरी का उत्पादन कर रहे हैं और पुस्तकालय नहीं है, तो यह भी ठीक है।


5

(मुझे पता है कि मुझे पार्टी में देर हो रही है लेकिन यह अभी भी दूसरों के लिए उपयोगी हो सकता है)

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


3

इन पंक्तियों के साथ, मैं विरोधी अनाथ उदाहरण शिविर की स्थिति WRT पुस्तकालयों को समझता हूं, लेकिन निष्पादन योग्य लक्ष्यों के लिए अनाथ उदाहरण ठीक नहीं होने चाहिए?


3
दूसरों को अपवित्र होने के मामले में, आप सही हैं। लेकिन आप अपने आप को संभावित भविष्य की समस्याओं के लिए खोल रहे हैं यदि उसी उदाहरण को भविष्य में कभी आपकी निर्भरता श्रृंखला में कहीं परिभाषित किया गया हो। तो इस मामले में, यह तय करना आपके लिए है कि क्या यह जोखिम के लायक है।
यिट्ज

5
एक निष्पादन में एक अनाथ उदाहरण को लागू करने के लगभग सभी मामलों में, यह एक अंतर को भरना है जो आप चाहते हैं कि आपके लिए पहले से ही परिभाषित किया गया था। इसलिए यदि उदाहरण ऊपर की ओर दिखाई देता है, तो परिणामस्वरूप संकलित त्रुटि एक उपयोगी संकेत है जो आपको यह बताने के लिए है कि आप अपने उदाहरण की घोषणा को हटा सकते हैं।
बेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.