2015-02-06 5 views
19

मैं हास्केल में श्रेणियों के निम्नलिखित व्यवहार को समझ नहीं सकता। 1 से 1 की गणना करने से मुझे एक सूची केवल 1 होती है, और 2 से 2 में मुझे एक सूची देता है जैसा कि नीचे दिया गया है। जैसा कि नीचे दिखायायदि मैं जीएचसीआई पर [1/0..1/0] दर्ज करता हूं तो मुझे अनंत अनंतता मिल रही है। क्यूं कर?

Prelude> [1..1] 
[1] 
Prelude> [2..2] 
[2] 

लेकिन अनंत को अनंत की गणना मुझे एक सूची है जो लंबाई में अनंत है और सभी तत्वों को देता है, अनंत है।

Prelude> [1/0..1/0] 
[Infinity,Infinity,Infinity,Infinity,Infinity,Infinity,Interrupted. 

मुझे पता है कि इन्फिनिटी एक अवधारणा है जिसे एक संख्या के रूप में नहीं माना जाना चाहिए, लेकिन उस व्यवहार को क्या औचित्य देता है?

+8

यह वास्तव में आईईईई 754 के गैर-वास्तविक-संख्या मूल्यों के कई अन्य परिणामों की तुलना में अधिक उचित है। – leftaroundabout

उत्तर

31

हास्केल के Double (डिफ़ॉल्ट जब / का उपयोग कर आप प्राप्त) जो परिभाषित करता है कि कैसे Infinity बर्ताव चल बिन्दु संख्या के लिए IEEE 754 standard इस प्रकार है,। यही कारण है कि 1/0Infinity है।

इस मानक (और,, निष्पक्ष होना करने के लिए तर्क के आधार पर), Infinity + 1 == Infinity, और Double के लिए Enum उदाहरण तक सिर्फ 1 हर बार कहते हैं।

यह एक और संकेत है कि EnumDouble के लिए उदाहरण पूरी तरह से अच्छी तरह से गठित नहीं है और आमतौर पर Enum उदाहरणों के लिए अपेक्षाओं के अनुरूप नहीं है। तो, अंगूठे के नियम के रूप में, आपको शायद .. का उपयोग फ्लोटिंग पॉइंट नंबरों के लिए करना चाहिए: भले ही आप समझें कि यह कैसे काम करता है, यह आपके कोड को पढ़ने वाले लोगों के लिए भ्रमित होगा। उलझनपूर्ण व्यवहार का एक और उदाहरण के रूप में, पर विचार करें:

Prelude> [0.1..1] 
[0.1,1.1] 

आप में Double के लिए एक बहुत Enum उदाहरण के बारे में अधिक जानकारी प्राप्त करना चाहते हैं, तो आप इस pretty lengthy Haskell-cafe thread के माध्यम से पढ़ सकते हैं।

+0

आकस्मिक डाउनवोट के बारे में खेद है- जैसे ही इसे लॉक नहीं किया जाएगा, मैं इसे हटा दूंगा। – Slade

+0

@ स्लेड: आह, कोई समस्या नहीं। मैंने कुछ और पढ़ने के लिए एक लिंक जोड़ा, इसलिए आपका वोट अब और लॉक नहीं होना चाहिए। –

3

मेरा मानना ​​है कि [a..b] का कार्यान्वयन a बढ़ रहा है जब तक यह b से अधिक न हो। यह अनंतता के साथ कभी नहीं होने वाला है, इसलिए यह हमेशा के लिए जाता है।

मेरा मानना ​​है कि आपका कोड संभवतः Double पर डिफॉल्ट होगा, जिसने इसे लिखा है, जिसमें अनंतता के लिए अच्छी तरह से परिभाषित अर्थशास्त्र है। आईआईआरसी, हास्केल http://en.wikipedia.org/wiki/IEEE_floating_point का पालन करता है।

13

लुइस Wasserman और टिकोन Jelvis के रूप में संकेत दिया है, बुनियादी समस्या यह है कि Float और Double के लिए Num और Enum उदाहरणों अजीब हैं, और वास्तव में मौजूद ही नहीं चाहिए। वास्तव में, Enum वर्ग स्वयं बहुत अजीब है, क्योंकि यह एक साथ कई अलग-अलग उद्देश्यों को पूरा करने का प्रयास करता है, उनमें से कोई भी अच्छी तरह से नहीं है- यह शायद एक ऐतिहासिक दुर्घटना और सुविधा के रूप में सबसे अच्छा माना जाता है, जो कि टाइपक्लास जैसा दिखना चाहिए । Num और Integral कक्षाओं की एक महत्वपूर्ण सीमा तक, यह भी सच है। इन कक्षाओं में से किसी एक का उपयोग करते समय, आपको उन विशिष्ट प्रकारों पर ध्यान देना होगा जिन पर आप काम कर रहे हैं।चल बिन्दु के लिए

enumFromTo तरीकों का पालन समारोह पर आधारित हैं:

numericEnumFromTo :: (Ord a, Fractional a) => a -> a -> [a] 
numericEnumFromTo n m = takeWhile (<= m + 1/2) (numericEnumFrom n) 

तो 2 <= 1+1/2झूठी है, लेकिन चल बिन्दु के weirdness की वजह से, infinity <= infinity + 1/2सच है।

जैसा कि टिखॉन जेल्विस इंगित करता है, आमतौर पर फ्लोटिंग पॉइंट के साथ संख्यात्मक श्रेणियों सहित Enum विधियों का उपयोग नहीं करना सबसे अच्छा होता है।

+0

succ। यही कारण है कि फ्रीज में 'एनम डबल' या 'एनम फ्लोट' नहीं है। – Ingo

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