2011-08-14 11 views
26

हास्केल में टाइप अनुमान में थोड़ा सीखने की वक्र है (कम से कम कहने के लिए!)। सीखना शुरू करने का एक अच्छा तरीका सरल उदाहरणों के साथ है। तो, टाइप अनुमान के लिए निम्नलिखित "हैलो वर्ल्ड" का थोड़ा सा है।क्यों 3 और एक्स (जिसे 3 असाइन किया गया था) में हास्केल में अलग-अलग अनुमानित प्रकार क्यों हैं?

निम्न उदाहरण पर विचार करें:

Prelude> :t 3 
3 :: (Num t) => t 
Prelude> let x = 3 
Prelude> :t x 
x :: Integer 

प्रश्न इस प्रकार है: क्यों 3 और एक्स विभिन्न प्रकार है?

लिंक सारांश:

पूरी कहानी के लिए नीचे दिए गए जवाब पढ़ें; यहां सिर्फ एक लिंक सारांश है:

  1. GHC प्रकार सामान्यिंग: Haskell Report section 4.3.4
  2. GHCi के विस्तारित प्रकार सामान्यिंग: Using GHCi section 2.4.5
  3. monomorphic प्रतिबंध: Haskell wiki
+0

हां, नया शीर्षक पुराना एक से अधिक विशिष्ट/स्पष्ट है! –

+0

मैंने अपने मूल प्रश्न के निचले हिस्से को हटा दिया; वारंट समावेशन के लिए पर्याप्त मूल्य नहीं जोड़ रहा था। –

उत्तर

32

यहां एक और कारक है, जिसमें कुछ लिंक शामिल हैं जो एफ़ोल्टर में शामिल हैं, लेकिन यह स्पष्ट रूप से यहां लायक हो सकता है। आप monomorphism restriction के प्रभाव का सामना कर रहे हैं। जब आप कहते हैं कि

let x = 5 

आप एक चर के उच्च-स्तरीय परिभाषा बनाते हैं। एमआर जोर देकर कहते हैं कि ऐसी परिभाषाएं, जब किसी अन्य प्रकार के हस्ताक्षर से अनजान हों, तो अनसुलझे प्रकार चर के लिए उपयुक्त उम्मीदों को चुनकर (उम्मीदपूर्वक) चुनकर एक मोनोमोर्फिक मान के लिए विशिष्ट होना चाहिए। इसके विपरीत, जब आप अनुमानित प्रकार के लिए पूछने के लिए :t का उपयोग करते हैं, तो ऐसा कोई प्रतिबंध या डिफ़ॉल्ट नहीं लगाया जाता है। तो

> :t 3 
3 :: (Num t) => t 

क्योंकि 3 वास्तव में ओवरलोड हो गया है: यह किसी भी सांख्यिक प्रकार के आधार पर भर्ती कराया गया है। दोषी नियम Integer डिफ़ॉल्ट संख्यात्मक प्रकार के रूप में, तो

> let x = 3 
> :t x 
x :: Integer 

चुनें लेकिन अब के एमआर बंद कर देते हैं।

> :set -XNoMonomorphismRestriction 
> let y = 3 
> :t y 
y :: (Num t) => t 

एमआर के बिना, परिभाषा बस के रूप में बहुरूपी के रूप में यह हो सकता है, बस के रूप में के रूप में 3 अतिभारित है। बस जाँच रहा हूँ...

> :t y * (2.5 :: Float) 
y * (2.5 :: Float) :: Float 
> :t y * (3 :: Int) 
y * (3 :: Int) :: Int 

ध्यान दें कि बहुरूपी y = 3 अलग ढंग से, इन उपयोगों में विशेषज्ञता प्राप्त की जा रही है fromInteger विधि प्रासंगिक Num उदाहरण के साथ आपूर्ति के अनुसार। यही है, y के एक विशेष प्रतिनिधित्व से जुड़ा हुआ नहीं है, बल्कि के प्रतिनिधित्व के निर्माण के लिए एक योजना है। नाइली संकलित, यह धीमी गति के लिए एक नुस्खा है, जो कुछ लोग एमआर के लिए प्रेरणा के रूप में उद्धृत करते हैं।

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

जब जानने के लिए कैसे प्रकार प्रणाली काम करता है की कोशिश कर रहा है, यह प्रकार निष्कर्ष के पहलुओं जो

  1. ‘ योजना ’, विशेष रूप से उपयोग के मामलों को बहुरूपी परिभाषाओं विशेषज्ञता का पालन अलग करने के लिए वास्तव में उपयोगी है: एक काफी मजबूत मामला बाधा को हल करने के लिए, बैकचेनिंग द्वारा मूल एकीकरण और उदाहरण संकल्प की आवश्यकता होती है; और

  2. ‘ लगता योजना ’, प्रकार सामान्यीकरण कोई प्रकार हस्ताक्षर के साथ एक परिभाषा के लिए एक बहुरूपी प्रकार योजना आवंटित करने के लिए: इससे काफी नाजुक है, और अधिक आप प्रकार वर्गों के साथ अतीत बुनियादी Hindley-मिलनर अनुशासन ले जाते हैं,, जीएडीटी के साथ उच्च रैंक बहुरूपता, अजनबी चीजें बन जाती हैं।

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

+3

एमआर के बारे में आपकी राय जो भी संकलित कार्यक्रमों के लिए है, हर कोई इस बात से सहमत है कि यह इस उदाहरण में जीएचसीआई प्रॉम्प्ट पर डिफ़ॉल्ट रूप से प्रभावी नहीं होना चाहिए। [जीएचसी बग # 3202] (http://hackage.haskell.org/trac/ghc/ticket/3202) इसे ठीक करता है। यह 7.2.1 में होना निर्धारित था जिसे अभी जारी किया गया था, लेकिन ऐसा लगता है कि यह इसे नहीं बना रहा। उम्मीद है कि यह जीएचसी के अगले संस्करण में तय किया जाएगा। – Yitz

+2

@Yitz यह वास्तव में एक अच्छा परिणाम होगा। मैं यह कहने के इच्छुक हूं कि एमआर डिफ़ॉल्ट रूप से बंद होना चाहिए, लेकिन मौजूदा कोडबेस में कितनी प्रकार की/प्रदर्शन समस्याएं पेश की जाएंगी, इस बारे में कठिन डेटा इकट्ठा करना अच्छा होगा। मुझे यह भी आश्चर्य है कि क्या जीएचसी की विशेषज्ञता मशीनरी हमें दोनों तरीकों से रखने की अनुमति दे सकती है। लेकिन मैं अनुमान लगाता हूं। – pigworker

+0

"एमआर जोर देकर कहते हैं कि ऐसी परिभाषाएं, जब किसी अन्य प्रकार के हस्ताक्षर से अनजान हो, को एक मोनोमोर्फिक मूल्य के लिए विशिष्ट होना चाहिए" मैं थोड़ी देर के लिए एमआर को समझने की कोशिश कर रहा हूं, लेकिन अभी भी काफी नहीं है ... मैं समझ सकता हूं अगर एमआर ने आपको हस्ताक्षर निर्दिष्ट करने के लिए मजबूर किया है, लेकिन बस कुछ प्रकार के लिए डिफॉल्ट करना मेरे लिए सबसे खराब विकल्प जैसा लगता है। – dainichi

6

यह, के रूप में चर्चा here, type defaulting in GHCi के कारण होती है here , here, और here, दूसरों के बीच। दुर्भाग्यवश ऐसा कुछ ऐसा लगता है जो खोजना मुश्किल है, क्योंकि इस शब्द का वर्णन करने के कई तरीके हैं जो आपको "टाइपिंग डिफॉल्टिंग" वाक्यांश से पहले जानते हैं।

अद्यतन: डी ओह। खराब उदाहरण हटा दिया गया।

+6

एहरम, यह उत्तर बहुत भ्रामक है। 'X' के प्रकार 'Num a => a' के लिए यह बिल्कुल ठीक होगा। वास्तव में यदि आप मोनोमोर्फिज्म प्रतिबंध को अक्षम करते हैं या स्पष्ट रूप से 'x' इस प्रकार देते हैं, तो उस प्रकार का प्रकार होगा। और उस स्थिति में 'x * 3.0' करने के बारे में कोई दिक्कत नहीं है। संख्यात्मक प्रकारों के लिए भी डिफ़ॉल्ट रूप से ghci- विशिष्ट नहीं है। – sepp2k

+0

@ sepp2k: gah, monomorphism प्रतिबंध तब भी हमला करता है जब मैं सवालों का जवाब देने का प्रयास करता हूं! तुम बिल्कुल सही हो – acfoltzer

+0

@ sepp2k: टाइप अनुमान और टाइपिंग के बीच कनेक्शन के लिए धन्यवाद! मैं सहमत हूं, पूर्व की तलाश करना जरूरी नहीं है कि बाद वाले को उजागर करें। –

4

चूंकि किसी और ने का उल्लेख नहीं किया है क्यों एक मोनोमोर्फिज्म प्रतिबंध है, मैंने सोचा कि मैं A History of Haskell: Being Lazy With Class से यह बिट जोड़ूंगा।

6,2 monomorphism प्रतिबंध प्रारंभिक दौर में विवाद का एक प्रमुख स्रोत तथाकथित "monomorphism प्रतिबंध था।" मान लीजिए genericLength इस अतिभारित प्रकार है:

genericLength :: Num a => [b] -> a 

अब इस डी फाई nition पर विचार करें:

f xs = (len, len) 
    where len = genericLength xs 

यह ऐसा है len केवल एक बार गणना की जानी चाहिए है, लेकिन यह वास्तव में दो बार की जा सकती है। क्यूं कर? क्योंकि हम len :: (Num a) => a प्रकार का अनुमान लगा सकते हैं; जब 0 -अनुवाद के साथ डेज्यूग्रेड किया गया, len एक ऐसा फ़ंक्शन बन जाता है जिसे प्रत्येक len की घटना के लिए एक बार कहा जाता है, जिनमें से प्रत्येक एक अलग प्रकार पर उपयोग किया जा सकता है।

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

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

मोनोमोर्फिज्म प्रतिबंध स्पष्ट रूप से भाषा पर एक वार्ट है। यह एक अप्रत्याशित या अस्पष्ट त्रुटि संदेश को जन्म देकर हर नए हास्केल प्रोग्रामर काटने का प्रतीत होता है। विकल्पों की बहुत चर्चा हुई है। ग्लासगो हास्केल कंपाइलर (GHC, धारा 9.1) एक fl एजी प्रदान करता है:

-fno-monomorphism-restriction 

प्रतिबंध पूरी तरह दबाने के लिए। लेकिन इस समय, वास्तव में संतोषजनक विकल्प विकसित नहीं हुआ है।

मुझे लगता है कि मोनोमोर्फिज्म प्रतिबंध की ओर पेपर का स्वर बहुत दिलचस्प है।

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