2015-09-28 9 views
6

मैं हास्केल पर एक व्याख्यान टिप्पणी पढ़ने जब मैं इस पैरा (http://www.seas.upenn.edu/~cis194/lectures/02-lists.html) में आए किया गया था:हास्केल में मिरर टाइप करें?

यह "देखभाल नहीं" है क्या "पैरामीट्रिक" पैरामीट्रिक पोलिमोर्फ़िज्मके साधन में। सभी हास्केल फ़ंक्शंस अपने प्रकार के पैरामीटर में पैरामीट्रिक होना चाहिए; इन पैरामीटर के विकल्पों के आधार पर कार्यों को परवाह नहीं करना चाहिए या निर्णय नहीं लेना चाहिए। एक कार्य एक चीज नहीं कर सकता है जब एक इंट है और बूल होने पर एक अलग बात है। हास्केल बस इस तरह के एक ऑपरेशन लिखने के लिए कोई सुविधा प्रदान नहीं करता है। लैंगेज की इस संपत्ति को पैरामीट्रिक कहा जाता है।

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

क्या मुझे समझ नहीं आता है कि कैसे कर रहे हैं "सभी हास्केल कार्यों" पैरामीट्रिक? हास्केल में स्पष्ट/स्थैतिक प्रकार नहीं हैं? इसके अलावा मैं वास्तव में समझ नहीं पा रहा हूं कि कैसे टाइप एरर संकलित समय रनटाइम में सुधार करता है?

क्षमा करें अगर ये प्रश्न वास्तव में बुनियादी हैं, तो मैं हास्केल के लिए नया हूं।

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

एक और सवाल: क्यों लेखक कहता है कि "कैसे महत्वपूर्ण प्रकार कर रहे हैं जब हास्केल कोड लिखने के बावजूद, वे पूरी तरह से अप्रासंगिक हैं जब हास्केल कोड चलाने"?

+2

उद्धरण कभी दावा नहीं करता है कि "टाइप एरर संकलन समय में सुधार करता है", केवल यह है कि यह _runtime_ में सुधार करने में मदद करता है। – chi

+0

फ़ंक्शंस पैरामीट्रिक हैं यदि आपके पास टाइप पैरामीटर 'ए' है, तो आप कभी भी' ए 'का निरीक्षण नहीं कर सकते हैं और रनटाइम पर इसके प्रकार के आधार पर निर्णय ले सकते हैं। तो आप निश्चित हो सकते हैं कि 'मानचित्र' जैसे फ़ंक्शन सभी इनपुट सूचियों के लिए समान रूप से व्यवहार करते हैं, इसलिए आपको रनटाइम पर सूची तत्व प्रकार को बनाए रखने की आवश्यकता नहीं है। इसे सी # जैसी भाषा से तुलना करें जो आपको वास्तविक सूची पैरामीटर प्रकार को प्रतिबिंब के माध्यम से रनटाइम पर प्राप्त करने की अनुमति देता है। – Lee

उत्तर

13

मुझे क्या समझ में नहीं आता है कि "सभी हास्केल फ़ंक्शंस" पैरामीट्रिक कैसे हैं?

यह कहना नहीं है सब हास्केल कार्यों पैरामीट्रिक हैं, यह कहते हैं:

सभी हास्केल कार्यों पैरामीट्रिक होना चाहिए उनके प्रकार पैरामीटर में

एक हास्केल फ़ंक्शन में कोई प्रकार पैरामीटर नहीं होना चाहिए।

एक और सवाल: लेखक क्यों कहते हैं कि "हास्केल कोड लिखते समय कितने महत्वपूर्ण प्रकार हैं, बावजूद हास्केल कोड चलाते समय वे पूरी तरह से अप्रासंगिक हैं"?

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

हास्केल में स्पष्ट/स्थैतिक प्रकार नहीं हैं?

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

2

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

8

प्रकार हास्केल में मिटाया जा सकता है क्योंकि अभिव्यक्ति का प्रकार या तो संकलन समय (जैसे True) पर पता है या इसका प्रकार रनटाइम पर कोई फर्क नहीं पड़ता (जैसे [])।

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

5

अन्य पहले ही उत्तर दे चुके हैं, लेकिन शायद कुछ उदाहरण मदद कर सकते हैं।

अजगर, उदाहरण के लिए, को बरकरार रखे हुए क्रम तक टाइप जानकारी:

>>> def f(x): 
... if type(x)==type(0): 
...  return (x+1,x) 
... else: 
...  return (x,x) 
... 
>>> f("hello") 
('hello', 'hello') 
>>> f(10) 
(11, 10) 

समारोह से ऊपर, किसी भी तर्क x जोड़ी (x,x), रिटर्न को छोड़कर जब x प्रकार int की है दिया। रनटाइम पर उस प्रकार के फ़ंक्शन परीक्षण, और यदि xint पाया जाता है तो यह एक विशेष तरीके से व्यवहार करता है, इसके बजाय (x+1, x) लौटाता है।

उपरोक्त को समझने के लिए, पायथन रनटाइम को प्रकारों का ट्रैक रखना चाहिए। यही कारण है, जब हम करते हैं

>>> x = 5 

अजगर सिर्फ स्मृति में 5 की बाइट प्रतिनिधित्व की दुकान नहीं कर सकते हैं। इसे उस प्रकार के प्रतिनिधित्व को int के साथ चिह्नित करने की भी आवश्यकता है, ताकि जब हम type(x) करते हैं तो टैग पुनर्प्राप्त किया जा सकता है।

आगे, x+1 जैसे किसी भी ऑपरेशन करने से पहले पायथन को यह सुनिश्चित करने के लिए टाइप टैग की जांच करने की आवश्यकता है कि हम वास्तव में int पर काम कर रहे हैं। यदि x उदाहरण के लिए str आईएनजी है, तो पायथन एक अपवाद उठाएगा।

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

SomeClass x = new SomeClass(42); 
x.foo(); 

संकलक पहले से ही जाँच की है कि वहां वास्तव संकलन समय पर x के लिए एक विधि foo है, ताकि फिर से करने की आवश्यकता नहीं है। यह सिद्धांत रूप में प्रदर्शन में सुधार कर सकते हैं। (वास्तव में, JVM वर्ग लोड करते समय कुछ क्रम चेकों करता है, लेकिन के सादगी की खातिर उन पर ध्यान न दें चलो)

ऊपर के बावजूद, जावा दुकान प्रकार टैग करने के लिए अजगर की तरह, है क्योंकि यह एक है type(-) अनुरूप:

if (x instanceof SomeClass) { ... 

इसलिए, जावा एक कार्य करता है जो "विशेष रूप से" कुछ प्रकार पर उनके व्यवहार कर सकते हैं लिखने के लिए अनुमति देता है।

// this is a "generic" function, using a type parameter A 
<A> A foo(A x) { 
    if (x instanceof B) { // B is some arbitrary class 
     B b = (B) x; 
     return (A) new B(b.get()+1); 
    } else { 
     return x; 
    } 
} 

ऊपर समारोह foo() बस इसके तर्क देता है, जब यह प्रकार B, जिसके लिए एक नई वस्तु के बजाय बनाई गई है की स्थिति को छोड़कर। यह instanceof का उपयोग करने का एक परिणाम है, जिसके लिए प्रत्येक ऑब्जेक्ट को रनटाइम पर टैग ले जाने की आवश्यकता होती है।

ईमानदार होने के लिए, ऐसा टैग आभासी तरीकों को लागू करने में सक्षम होने के लिए पहले से मौजूद है, इसलिए इसका कोई और खर्च नहीं होता है। फिर भी, instanceof की उपस्थिति से उपर्युक्त गैर-वर्दी व्यवहार को प्रकारों पर संभव बनाता है - कुछ प्रकारों को अलग-अलग संभाला जा सकता है।

हास्केल, इसके बजाय type/instanceof ऑपरेटर नहीं है। एक पैरामीट्रिक हास्केल समारोह होने प्रकार

foo :: a -> (a,a) 

चाहिए सभी प्रकार में एक ही तरह से व्यवहार। कुछ "विशेष" व्यवहार का कोई कारण नहीं है। Concretely, foo x वापसी (x,x), और हम इसे उपरोक्त प्रकार की एनोटेशन देखकर देख सकते हैं। इस बिंदु पर दबाव डालने के लिए, ऐसी संपत्ति साबित करने के लिए कोड (!!) को देखने की आवश्यकता नहीं है। यह पैरामीट्रिकिटी उपर्युक्त प्रकार से सुनिश्चित करता है।

+0

जावा उदाहरण मेरे लिए बहुत अच्छा प्रतीत नहीं होता है। पहले उदाहरण में, 'foo' को आम तौर पर * * में * रनटाइम प्रकार की जांच शामिल होती है, क्योंकि JVM को यह निर्धारित करना होता है कि' SomeClass' के कुछ उप-वर्ग में 'foo' विधि को ओवरराइड किया गया है या नहीं। और दूसरे में, 'ए' पर कास्ट तीन गुना गलत है: आप किसी प्रकार के पैरामीटर (मिटाए जाने के कारण) के रूप में नहीं डाले जा सकते हैं; कन्स्ट्रक्टर कॉल कास्टिंग करने का कोई भी उपयोग कभी नहीं होता है, क्योंकि इसका प्रकार पूरी तरह से ज्ञात है; वैसे भी किसी भी तरह कास्ट करने की आवश्यकता नहीं है क्योंकि इस संदर्भ में 'बी' स्पष्ट रूप से 'ए' का उप-वर्ग है। – amalloy

+0

@amalloy 1) मुझे पूरी तरह से यकीन नहीं है, लेकिन मुझे लगता है कि vtable तक पहुंचने और विधि को बुलाकर वहां कुछ भी जांचने की आवश्यकता नहीं है, केवल अंधाधुंध बिंदुओं का पालन करने के लिए; 2) '(ए)' कास्ट के बिना कोड संकलित करने का प्रयास करें: संकलक सही मायने में शिकायत करता है कि 'बी' सामान्य 'ए' का उप-प्रकार नहीं है। (रनटाइम पर अनचेक कास्ट के बारे में एक चेतावनी है, हालांकि) – chi

+0

उचित बिंदु (1) मुझे लगता है। आप (2) के बारे में क्या कहते हैं, यह सच है, लेकिन वास्तव में आपके उत्तर का समर्थन नहीं करता है: कि कास्ट रनटाइम पर नहीं होता है; यह शून्य बाइटकोड ऑपरेशंस (या, ठीक है, संभवतः ऑब्जेक्ट में एक कास्ट, जो मूल रूप से नो-ऑप है) तक संकलित करता है।कंपाइलर को खुश करने के लिए संकलन समय की आवश्यकता है, लेकिन रनटाइम पर कुछ भी नहीं करता है। – amalloy

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