हास्केल का प्रकार चेकर उचित है। समस्या यह है कि आपके द्वारा उपयोग किए जा रहे पुस्तकालय के लेखकों ने कुछ किया है ... कम उचित।
संक्षिप्त उत्तर है: हाँ, 10 :: (Float, Float)पूरी तरह से वैध है यदि कोई उदाहरण है Num (Float, Float)। संकलक या भाषा के दृष्टिकोण से इसके बारे में "बहुत गलत" कुछ भी नहीं है। यह सिर्फ हमारे अंतर्ज्ञान के साथ वर्ग नहीं करता है कि संख्यात्मक अंक क्या करते हैं। जब से आप टाइप की गई प्रणाली को पकड़ते हैं, तो आप जिस तरह की त्रुटि करते हैं, आप हैरान और निराश होते हैं!
Numउदाहरण और fromIntegerसमस्या
आप हैरान हैं कि कंपाइलर स्वीकार करता है 10 :: Coord, यानी 10 :: (Float, Float)। यह मान लेना उचित है कि जैसे संख्यात्मक शाब्दिक 10"सांख्यिक" प्रकार के लिए अनुमानित होंगे। बॉक्स से बाहर, संख्यात्मक शाब्दिक व्याख्या की जा सकती रूप में Int, Integer, Float, या Double। किसी अन्य संदर्भ के साथ संख्याओं का एक प्रकार, उन चार प्रकारों की संख्याओं के तरीके की तरह नहीं लगता है। हम बात नहीं कर रहे हैं Complex।
सौभाग्य से या दुर्भाग्य से, हालांकि, हास्केल एक बहुत ही लचीली भाषा है। मानक निर्दिष्ट करता है कि एक पूर्णांक शाब्दिक की 10व्याख्या की जाएगी fromInteger 10, जिसका प्रकार है Num a => a। तो किसी भी प्रकार के बारे में 10अनुमान लगाया जा सकता है कि इसके लिए एक उदाहरण लिखा गया था। मैं इसे एक और जवाब में थोड़ा और विस्तार से समझाता हूं ।Num
इसलिए जब आप अपना प्रश्न पोस्ट करते हैं, तो एक अनुभवी हास्केलर तुरंत स्पॉट करता है कि 10 :: (Float, Float)स्वीकार किए जाने के लिए, एक उदाहरण होना चाहिए जैसे Num a => Num (a, a)या Num (Float, Float)। इसमें ऐसा कोई उदाहरण नहीं है Prelude, इसलिए इसे कहीं और परिभाषित किया गया होगा। उपयोग करते हुए :i Num, आप जल्दी से स्पॉट हुए कि यह कहाँ से आया है: glossपैकेज।
टाइप पर्यायवाची और अनाथ उदाहरण
लेकिन एक मिनट पकड़ो। आप glossइस उदाहरण में किसी भी प्रकार का उपयोग नहीं कर रहे हैं ; glossआपको प्रभावित करने का उदाहरण क्यों दिया गया ? जवाब दो चरणों में आता है।
सबसे पहले, कीवर्ड के साथ पेश किया गया एक प्रकार का पर्याय typeएक नया प्रकार नहीं बनाता है । आपके मॉड्यूल में, लेखन Coordकेवल इसके लिए शॉर्टहैंड है (Float, Float)। इसी तरह Graphics.Gloss.Data.Point, Pointसाधन में (Float, Float)। दूसरे शब्दों में, अपने Coordऔर glossकी Pointसचमुच बराबर हैं।
इसलिए जब glossअनुरक्षकों ने लिखना चुना instance Num Point where ..., तो उन्होंने आपके Coordप्रकार को भी एक उदाहरण बना दिया Num। के बराबर instance Num (Float, Float) where ...या है instance Num Coord where ...।
(डिफ़ॉल्ट रूप से, हास्केल प्रकार के समानार्थक शब्द को वर्ग उदाहरण नहीं बनने देते हैं। glossलेखकों को भाषा एक्सटेंशन की एक जोड़ी को सक्षम करना था, TypeSynonymInstancesऔर FlexibleInstances, उदाहरण के लिए लिखना होगा।)
दूसरा, यह आश्चर्य की बात है क्योंकि यह एक अनाथ उदाहरण है , अर्थात एक उदाहरण घोषणा instance C Aजहां दोनों Cऔर Aअन्य मॉड्यूल में परिभाषित किए गए हैं। यहाँ यह क्योंकि प्रत्येक भाग शामिल विशेष रूप से घातक है, यानी Num, (,)है, और Float, से आता है Preludeऔर हर जगह दायरे में रहने की संभावना है।
आपकी अपेक्षा है कि Numपरिभाषित किया गया है Preludeऔर tuples और Floatमें परिभाषित कर रहे हैं Prelude, तो उन तीन चीजों के बारे में सब कुछ कैसे काम में परिभाषित किया गया है Prelude। आयात करने से पूरी तरह से अलग मॉड्यूल कुछ भी क्यों बदल जाएगा? आदर्श रूप से यह नहीं होगा, लेकिन अनाथ उदाहरण उस अंतर्ज्ञान को तोड़ते हैं।
(ध्यान दें कि GHC अनाथ उदाहरणों के बारे में चेतावनी देता है - glossविशेष रूप से उस चेतावनी को ओवररोड करने वाले लेखक । यह लाल झंडा उठाया जाना चाहिए और प्रलेखन में कम से कम एक चेतावनी दी गई है।)
कक्षा के उदाहरण वैश्विक हैं और इन्हें छिपाया नहीं जा सकता है
इसके अलावा, वर्ग के उदाहरण वैश्विक हैं : किसी भी मॉड्यूल में परिभाषित कोई भी उदाहरण जो कि आपके मॉड्यूल से ट्रांसेटिव रूप से आयात किया जाता है, संदर्भ में होगा और उदाहरण के समाधान को करते समय टाइप-टेकर के लिए उपलब्ध होगा। यह वैश्विक तर्क को सुविधाजनक बनाता है, क्योंकि हम (आमतौर पर) मान सकते हैं कि (+)किसी दिए गए प्रकार के लिए एक क्लास फ़ंक्शन हमेशा समान रहेगा। हालाँकि, इसका यह भी अर्थ है कि स्थानीय निर्णयों के वैश्विक प्रभाव हैं; एक वर्ग उदाहरण को परिभाषित करने से अपस्ट्रीम कोड का संदर्भ बदल जाता है, जिसमें माड्यूल सीमाओं के पीछे मुखौटा या छुपाने का कोई तरीका नहीं है।
आप आयात सूचियों से बचने के लिए आयात सूचियों का उपयोग नहीं कर सकते । इसी तरह, आप उन मॉड्यूल से निर्यात करने से बच नहीं सकते जिन्हें आप परिभाषित करते हैं।
यह हास्केल भाषा डिजाइन का एक समस्याग्रस्त और बहुचर्चित क्षेत्र है। इस लाल धागे में संबंधित मुद्दों की एक आकर्षक चर्चा है । उदाहरण के लिए, उदाहरण के लिए दृश्यता नियंत्रण की अनुमति देने पर एडवर्ड केमेट की टिप्पणी: "आप मूल रूप से मेरे द्वारा लिखे गए लगभग सभी कोड की शुद्धता को फेंक देते हैं।"
(वैसे, जैसा कि इस उत्तर ने प्रदर्शित किया है , आप अनाथ उदाहरणों का उपयोग करके कुछ मामलों में वैश्विक-उदाहरण धारणा को तोड़ सकते हैं !)
क्या करना है - पुस्तकालय कार्यान्वयनकर्ताओं के लिए
लागू करने से पहले दो बार सोचें Num। आप के आसपास काम नहीं कर सकता fromInteger-कोई समस्या नहीं, को परिभाषित fromInteger = error "not implemented"करता है नहीं इसे बेहतर बनाने। क्या आपके उपयोगकर्ता भ्रमित या आश्चर्यचकित होंगे-या इससे भी बदतर, कभी नोटिस नहीं करेंगे - यदि उनके पूर्णांक शाब्दिक गलती से आपके द्वारा टाइप किए जाने वाले टाइप के लिए अनुमानित हैं? प्रदान कर रहा है (*)और (+)यह महत्वपूर्ण है — खासकर यदि आपको इसे हैक करना है?
Conal Elliott's vector-space(प्रकार के प्रकार *) या Edward Kmett linear(प्रकार के प्रकार * -> *) के लिए एक पुस्तकालय में परिभाषित वैकल्पिक अंकगणितीय ऑपरेटरों का उपयोग करने पर विचार करें । यह वही है जो मैं खुद करता हूं।
का उपयोग करें -Wall। अनाथ उदाहरणों को लागू न करें, और अनाथ उदाहरण चेतावनी को अक्षम न करें।
वैकल्पिक रूप से, linearऔर कई अन्य अच्छी तरह से व्यवहार किए गए पुस्तकालयों के नेतृत्व का पालन करें , और एक अलग मॉड्यूल में .OrphanInstancesया अनाथ उदाहरणों को प्रदान करें .Instances। और उस मॉड्यूल को किसी अन्य मॉड्यूल से आयात न करें । तब उपयोगकर्ता चाहें तो अनाथों को स्पष्ट रूप से आयात कर सकते हैं।
यदि आप अपने आप को अनाथों को परिभाषित करते हुए पाते हैं, तो संभव है और उचित होने पर, अपस्ट्रीम अनुरक्षकों को उन्हें लागू करने के लिए कहें। मैं अक्सर अनाथ उदाहरण लिखता था Show a => Show (Identity a), जब तक कि उन्होंने इसे नहीं जोड़ा transformers। मैंने इसके बारे में एक बग रिपोर्ट भी उठाई होगी; मुझे याद नहीं है।
क्या करना है - पुस्तकालय उपभोक्ताओं के लिए
आपके पास कई विकल्प नहीं हैं। लाइब्रेरी तक पहुंचने के लिए विनम्रतापूर्वक और रचनात्मक रूप से पहुंचें! उन्हें इस सवाल की ओर इशारा करें। समस्याग्रस्त अनाथ को लिखने के लिए उनके पास कुछ विशेष कारण हो सकते हैं, या वे सिर्फ महसूस नहीं कर सकते हैं।
अधिक व्यापक रूप से: इस संभावना से अवगत रहें। यह हास्केल के कुछ क्षेत्रों में से एक है जहां सच्चे वैश्विक प्रभाव हैं; आपको यह जाँचना होगा कि आपके द्वारा आयात किए जाने वाले प्रत्येक मॉड्यूल और उन मॉड्यूलों को आयात करने वाले प्रत्येक मॉड्यूल ने अनाथ उदाहरणों को लागू नहीं किया है। टाइप एनोटेशन कभी-कभी आपको समस्याओं के प्रति सचेत कर सकते हैं, और निश्चित रूप से आप :iजाँच करने के लिए जीएचसीआई में उपयोग कर सकते हैं ।
पर्यायवाची के newtypeबजाय अपने स्वयं के परिभाषित करें typeयदि यह पर्याप्त महत्वपूर्ण है। आपको पूरा यकीन है कि कोई भी उनके साथ गड़बड़ नहीं करेगा।
यदि आपको किसी ओपन-सोर्स लाइब्रेरी से बार-बार समस्याएँ आ रही हैं, तो आप निश्चित रूप से लाइब्रेरी का अपना संस्करण बना सकते हैं, लेकिन रखरखाव जल्दी सिरदर्द बन सकता है।