2011-11-24 19 views
16

क्यों है कि मैं क्या कर सकते हैं यह है:मैं हास्केल में डबल में इंटीजर क्यों नहीं जोड़ सकता?

1 + 2.0 

लेकिन जब मैं कोशिश:

let a = 1 
let b = 2.0 
a + b 

<interactive>:1:5: 
    Couldn't match expected type `Integer' with actual type `Double' 
    In the second argument of `(+)', namely `b' 
    In the expression: a + b 
    In an equation for `it': it = a + b 

यह सिर्फ सादा अजीब लगता है! क्या यह कभी आपको यात्रा करता है?

पीएस .: मुझे पता है कि "1" और "2.0" पॉलिमॉर्फिक स्थिरांक हैं। यह मुझे चिंता नहीं करता है। मुझे चिंता है कि हैस्केल पहले मामले में एक चीज़ करता है, लेकिन दूसरे दूसरे में!

+3

जैसा कि ज्ञापन जाता है, "इंटेग्रल से अधिक 'की आवश्यकता है"। –

+1

मुझे 'x.f() 'बनाम' g = x.f की याद दिलाता है; जी(); 'जावास्क्रिप्ट में। जब वेरिएबल्स प्रतिस्थापन मॉडल अमूर्त तोड़ते हैं तो यह बेकार हो जाता है। – hugomg

उत्तर

7

आप इस बारे में कुछ और जानने के लिए जीएचसीआई का उपयोग कर सकते हैं। अभिव्यक्ति के प्रकार को प्राप्त करने के लिए :t कमांड का उपयोग करें।

Prelude> :t 1 
1 :: Num a => a 

तो 1 एक निरंतर जो किसी भी सांख्यिक प्रकार (Double, Integer, आदि)

Prelude> let a = 1 
Prelude> :t a 
a :: Integer 
इस मामले में

तो किया जा सकता है, हास्केल inferred a के लिए ठोस प्रकार Integer है। इसी प्रकार, यदि आप let b = 2.0 लिखते हैं तो हास्केल Double टाइप करता है। let का उपयोग करके हास्केल ने अनुमान लगाया कि (शायद) आवश्यक से अधिक विशिष्ट प्रकार है, और इससे आपकी समस्या होती है। (मेरे से अधिक अनुभव वाला कोई भी व्यक्ति शायद इस मामले में क्यों टिप्पणी कर सकता है।) (+) के बाद Num a => a -> a -> a टाइप किया गया है, दो तर्कों को एक ही प्रकार की आवश्यकता है।

आप fromIntegral समारोह के साथ इसे ठीक कर सकते हैं:

Prelude> :t fromIntegral 
fromIntegral :: (Num b, Integral a) => a -> b 

इस समारोह अन्य सांख्यिक प्रकार के पूर्णांक प्रकार बदल देता है।

Prelude> let a = 1 
Prelude> let b = 2.0 
Prelude> (fromIntegral a) + b 
3.0 
+3

[मोनोमोर्फिज्म प्रतिबंध] (http://www.haskell.org/haskellwiki/Monomorphism_restriction) यही कारण है कि 'चलो' एक विशिष्ट प्रकार का चयन क्यों किया जाता है। आप इसे एक प्रकार के हस्ताक्षर देकर, या जीएचसीआई में 'सेट -XNoMonomorphismRestriction' (या संकलन के दौरान समकक्ष ध्वज) करके इसे ओवरराइड कर सकते हैं। – hammar

+0

क्या शिकायत करते समय ध्वज सेट करने की आवश्यकता है? मैंने सोचा कि संकलक "डिफ़ॉल्ट" नहीं करता है ... – drozzy

+0

@drozzy: यह करता है। जीएचसीआई के पास थोड़ा अलग डिफॉल्ट नियम हैं। सबसे विशेष रूप से, जीएचसीआई वर्ग की बाधाओं के एक बड़े सेट को डिफॉल्ट करने की इजाजत देता है, और यह डिफ़ॉल्ट प्रकारों की सूची में '()' जोड़ता है। – hammar

19

(+) का प्रकार हस्ताक्षर Num a => a -> a -> a के रूप में परिभाषित किया गया है, जिसका अर्थ यह है कि यह Num टाइपक्लास के किसी भी सदस्य पर काम करता है, लेकिन दोनों तर्क एक ही प्रकार के होने चाहिए।

यहां समस्या जीएचसीआई के साथ है और यह आदेश प्रकार स्थापित करता है, न कि हास्केल स्वयं। आप एक फ़ाइल (let भाव के लिए do का प्रयोग करके) यह संकलन और ठीक चल पाएंगे में अपने उदाहरणों में से एक डाल करने के लिए है, क्योंकि GHC संदर्भ के रूप में पूरे समारोह का उपयोग शाब्दिक 1 और 2.0 के प्रकार का निर्धारण करने के लिए थे, तो।

पहले मामले में जो कुछ भी हो रहा है वह है जीएचसीआई आपके द्वारा दर्ज की जा रही संख्याओं के प्रकार का अनुमान लगा रहा है। सबसे सटीक Double है, इसलिए यह मानता है कि दूसरा एक Double होना चाहिए और गणना को निष्पादित करता है। हालांकि, जब आप let अभिव्यक्ति का उपयोग करते हैं, तो इसमें केवल एक नंबर काम करने के लिए होता है, इसलिए यह 1 का निर्णय Integer और 2.0Double है।

संपादित करें: जीएचसीआई वास्तव में "अनुमान लगाने" नहीं है, यह हास्केल रिपोर्ट में परिभाषित बहुत विशिष्ट प्रकार के डिफ़ॉल्ट नियमों का उपयोग कर रहा है। आप here के बारे में कुछ और पढ़ सकते हैं।

+3

सबसे पहले, मैंने ऊपर उठाया। लेकिन जैसा कि मेरे पास नाइटपिकिंग की आदत है: एक स्थिर प्रकार प्रणाली विभिन्न प्रकारों की संख्या को ठीक करने में सहायता कर सकती है। यह सिर्फ इतना है कि हास्केल परिभाषा ('(+) :: संख्या एक => ए -> ए -> ए') की अनुमति नहीं देती है। (हालांकि यह टाइप अनुमान के साथ बहुत अच्छी तरह से नहीं खेलता है, जो संभवतः ऐसा नहीं किया गया है।) इसके अलावा, अगर आपका तर्क स्पष्ट रूप से ("अनुमान" यह न्याय IMHO नहीं करता है) तो आपका उत्तर स्पष्ट हो सकता है और तथ्य यह है कि शाब्दिक polymorphic हैं। – delnan

+3

"हास्केल में एक स्थिर प्रकार प्रणाली है, इसलिए आप कभी भी दो अलग-अलग प्रकारों को एक साथ जोड़ने में सक्षम नहीं होंगे।" यह oversimplification का थोड़ा सा है।कई भाषाओं में स्थैतिक प्रकार की व्यवस्था होती है और इन्हें युगल में जोड़ने की इजाजत मिलती है। यहां कीवर्ड यह है कि हास्केल का कोई अंतर्निहित रूपांतरण नहीं है। – sepp2k

+0

हाँ मुझे ऐसा नहीं लगता था कि मेरे पास टाइपिंग डिफॉल्टिंग पर पर्याप्त पर्याप्त हैंडल था और इसे समझाने के लिए। उस सामान के साथ अपना खुद का जवाब जोड़ने के लिए स्वतंत्र महसूस करें। –

11

पहले काम करता है क्योंकि संख्यात्मक शाब्दिक बहुरूपी होते हैं (। वे fromInteger literal resp के रूप में व्याख्या कर रहे हैं fromRational literal), इसलिए 1 + 2.0 में, तुम सच में fromInteger 1 + fromRational 2, अन्य बाधाओं का अभाव है, परिणाम प्रकार में है: उदाहरण के लिए Double पर डिफ़ॉल्ट।

दूसरा मोनोमोर्फिज्म प्रतिबंध की वजह से काम करता है। यदि आप किसी प्रकार के हस्ताक्षर के बिना कुछ और बाध्यकारी (name = expresion) के साथ कुछ बांधते हैं, तो उस इकाई को एक मोनोमोर्फिक प्रकार असाइन किया जाता है। शाब्दिक 1 के लिए, हमारे पास Num बाधा है, इसलिए defaulting rules के अनुसार, इसका प्रकार बाध्यकारी let a = 1 में Integer पर डिफ़ॉल्ट है। इसी तरह, fractional literal का प्रकार Double पर डिफॉल्ट किया गया है।

यदि आप :set -XNoMonomorphismRestriction ghci में काम करेंगे, तो यह काम करेगा।

मोनोमोर्फिज्म प्रतिबंध का कारण साझाकरण के नुकसान को रोकने के लिए है, यदि आप स्थिर मानते हुए एक मूल्य देखते हैं, तो आप इसकी अपेक्षा नहीं करते कि इसे एक से अधिक बार गणना की जाए, लेकिन यदि इसमें एक पॉलिमॉर्फिक प्रकार था, तो हर बार इसका इस्तेमाल किया जाएगा फिर से recomputed।

3

अन्य ने इस प्रश्न के कई पहलुओं को काफी अच्छी तरह संबोधित किया है। मैं + के प्रकार के हस्ताक्षर Num a => a -> a -> a के पीछे तर्क के बारे में एक शब्द कहना चाहता हूं।

सबसे पहले, Num टाइपक्लास के पास Num के एक कलात्मक उदाहरण को दूसरे में परिवर्तित करने का कोई तरीका नहीं है। मान लीजिए कि मेरे पास काल्पनिक संख्याओं के लिए डेटा प्रकार है; वे अभी भी संख्याएं हैं, लेकिन आप वास्तव में उन्हें केवल Int में परिवर्तित नहीं कर सकते हैं।

दूसरा, आप किस प्रकार के हस्ताक्षर पसंद करेंगे?

(+) :: (Num a, Num b) => a -> b -> a 
(+) :: (Num a, Num b) => a -> b -> b 
(+) :: (Num a, Num b, Num c) => a -> b -> c 

अन्य विकल्पों पर विचार करने के बाद, आपको एहसास है कि a -> a -> a सबसे आसान विकल्प है। पॉलिमॉर्फिक परिणाम (ऊपर तीसरे सुझाव में) शांत हैं, लेकिन कभी-कभी आसानी से उपयोग करने के लिए बहुत सामान्य हो सकते हैं।

तीसरा, हास्केल Blub नहीं है। अधिकांश, हालांकि तर्कसंगत रूप से, हास्केल के बारे में डिज़ाइन निर्णय लोकप्रिय भाषाओं के सम्मेलनों और अपेक्षाओं को ध्यान में रखते हैं। मैं अक्सर यह कहने का आनंद लेता हूं कि हास्केल सीखने का पहला कदम यह है कि आप प्रोग्रामिंग के बारे में जो कुछ भी जानते हैं उसे अनदेखा करना है। मुझे यकीन है कि ज्यादातर, अगर सभी नहीं, अनुभवी हैस्केलर्स को न्यू टाइपक्लास, और हास्केल की कई अन्य जिज्ञासाओं द्वारा पार किया गया है, क्योंकि अधिकांश ने पहले "मुख्यधारा" भाषा सीखी है। लेकिन धैर्य रखें, आप अंततः हास्केल निर्वाण तक पहुंच जाएंगे। :)

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

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