2009-06-14 8 views
207

मैं निम्नलिखित परिभाषा में आया क्योंकि मैं इसे चलाने के लिए एक असली परियोजना का उपयोग करके हास्केल सीखने की कोशिश करता हूं। मुझे समझ में नहीं आता कि प्रत्येक तर्क के सामने विस्मयादिबोधक चिह्न क्या है और मेरी किताबें इसका उल्लेख नहीं करतीं।हास्केल घोषणा में विस्मयादिबोधक चिह्न का क्या अर्थ है?

data MidiMessage = MidiMessage !Int !MidiMessage 
+12

मुझे संदेह है कि यह एक बहुत ही आम सवाल हो सकता है; मैं स्पष्ट रूप से ठीक उसी चीज के बारे में सोच रहा हूं, जिस तरह से वापस। –

उत्तर

255

यह एक सख्त घोषणा है। असल में, इसका मतलब यह है कि डेटा संरचना मूल्य बनने पर इसका मूल्यांकन "कमजोर सामान्य सिर फ़ॉर्म" कहलाता है।

data Foo = Foo Int Int !Int !(Maybe Int) 

f = Foo (2+2) (3+3) (4+4) (Just (5+5)) 

ऊपर समारोह f, जब मूल्यांकन किया, एक "thunk" वापस आ जाएगी: जो है, कोड अपने मूल्य पता लगाने की निष्पादित करने के लिए आइए एक उदाहरण को देखो तो यह है कि हम देख सकते हैं यह सिर्फ क्या मतलब है चलो । उस बिंदु पर, एक फू अभी तक कोड भी मौजूद नहीं है, बस कोड।

लेकिन कुछ बिंदु कोई शायद एक पैटर्न मैच के माध्यम से अंदर देखने के लिए, कोशिश कर सकते हैं पर:

case f of 
    Foo 0 _ _ _ -> "first arg is zero" 
    _   -> "first arge is something else" 

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

दूसरे को मूल्यांकन करने की आवश्यकता नहीं है, क्योंकि हम इसका परीक्षण नहीं कर रहे हैं। इस प्रकार, 6 उस स्मृति स्थान में संग्रहीत होने के बजाय, हम संभवतः बाद के मूल्यांकन के लिए कोड संग्रहीत करेंगे, (3+3)। अगर कोई इसे देखता है तो वह केवल 6 में बदल जाएगा।

तीसरा पैरामीटर, इसके सामने ! है, इसलिए सख्ती से मूल्यांकन किया जाता है: (4+4) निष्पादित किया गया है, और 8 उस स्मृति स्थान में संग्रहीत है।

चौथा पैरामीटर भी सख्ती से मूल्यांकन किया जाता है। लेकिन यहां वह थोड़ा मुश्किल हो गया है: हम पूरी तरह से मूल्यांकन नहीं कर रहे हैं, लेकिन केवल सामान्य सिर के रूप में कमजोर है। इसका मतलब यह है कि हम यह पता लगाते हैं कि यह Nothing या Just कुछ है, और उसे स्टोर करें, लेकिन हम आगे नहीं जाते हैं। इसका मतलब है कि हम Just 10 स्टोर नहीं करते हैं, लेकिन वास्तव में Just (5+5), बिना अनावश्यक अंदर थंक छोड़ते हैं। यह जानना महत्वपूर्ण है, हालांकि मुझे लगता है कि इस के सभी प्रभाव इस सवाल के दायरे से बाहर जाते हैं।

यदि आप BangPatterns भाषा एक्सटेंशन सक्षम, उसी तरह से समारोह तर्क टिप्पणी कर सकते हैं:

f x !y = x*y 

f (1+1) (2+2) thunk (1+1)*4 वापस आ जाएगी।

+12

यह बहुत उपयोगी है। मैं सोचने में मदद नहीं कर सकता कि क्या हास्केल शब्दावली लोगों को "कमजोर सामान्य सिर रूप", "सख्त" और आगे के शब्दों के साथ समझने के लिए चीजों को और अधिक जटिल बना रही है। अगर मैं आपको सही ढंग से समझता हूं, तो ऐसा लगता है! ऑपरेटर का मतलब है कि इसे बाद में मूल्यांकन करने के लिए अज्ञात ब्लॉक को संग्रहीत करने के बजाय अभिव्यक्ति के मूल्यांकन मूल्य को संग्रहीत करना है। क्या यह एक उचित व्याख्या है या इसके लिए कुछ और है? – David

+61

@ डेविड प्रश्न यह है कि मूल्य का मूल्यांकन कितना दूर है। कमजोर सिर सामान्य रूप का मतलब है: जब तक आप बाहरीतम कन्स्ट्रक्टर तक नहीं पहुंच जाते तब तक उसका मूल्यांकन करें। सामान्य रूप का मतलब है कि जब तक कोई मूल्यांकन नहीं किया जाता है तब तक पूरे मान का मूल्यांकन नहीं किया जाता है। क्योंकि हास्केल मूल्यांकन गहराई के स्तर के सभी प्रकार के लिए अनुमति देता है, इसका वर्णन करने के लिए एक समृद्ध शब्दावली है। आप उन भेदों को उन भाषाओं में नहीं ढूंढते हैं जो केवल कॉल-बाय-वैल्यू अर्थशास्त्र का समर्थन करते हैं। –

+7

@ डेविड: मैंने यहां एक और गहराई से स्पष्टीकरण लिखा है: [हास्केल: कमजोर हेड सामान्य फॉर्म क्या है?] (Http://stackoverflow.com/questions/6872898/haskell-what-is-weak-head-normal- प्रपत्र/6889335 # 6889335)। हालांकि मैं बैंग पैटर्न या सख्तता एनोटेशन का उल्लेख नहीं करता हूं, लेकिन वे 'seq' का उपयोग करने के बराबर हैं। – hammar

23

मेरा मानना ​​है कि यह एक कठोरता एनोटेशन है।

हास्केल एक शुद्ध और आलसी कार्यात्मक भाषा है, लेकिन कभी-कभी आलस्य का ऊपरी भाग बहुत अधिक या अपमानजनक हो सकता है। तो इससे निपटने के लिए, आप संकलक को चारों ओर पार्सिंग के बजाए फ़ंक्शन में तर्कों का पूर्ण मूल्यांकन करने के लिए कह सकते हैं।

इस पृष्ठ पर अधिक जानकारी है: Performance/Strictness

+0

हम्म, आपके द्वारा संदर्भित उस पृष्ठ पर उदाहरण का उपयोग करने के बारे में बात करना प्रतीत होता है! एक समारोह का आह्वान करते समय। लेकिन यह एक प्रकार की घोषणा में डालने से अलग लगता है। मैं क्या खो रहा हूँ? – David

+0

एक प्रकार का उदाहरण बनाना एक अभिव्यक्ति है। आप प्रकार के रचनाकारों को ऐसे कार्यों के रूप में सोच सकते हैं जो आपूर्ति किए गए तर्कों के अनुसार निर्दिष्ट प्रकार के नए उदाहरण लौटाते हैं। –

+1

वास्तव में, सभी उद्देश्यों और उद्देश्यों के लिए, रचनाकार टाइप करें * कार्य * हैं; आप आंशिक रूप से उन्हें लागू कर सकते हैं, उन्हें अन्य कार्यों (जैसे, 'मानचित्र [1,2,3] 'प्राप्त करने के लिए [बस 1, बस 2, बस 3] प्राप्त करने के लिए पास कर सकते हैं) और इसी तरह। मुझे उनके साथ पैटर्न मिलान करने की क्षमता के साथ-साथ पूरी तरह से असंबंधित सुविधा के बारे में सोचने में मदद मिलती है। –

67

सख्त और गैर-सख्त कन्स्ट्रक्टर तर्कों के बीच अंतर देखने का एक आसान तरीका यह है कि जब वे अपरिभाषित होते हैं तो वे व्यवहार करते हैं।

data Foo = Foo Int !Int 

first (Foo x _) = x 
second (Foo _ y) = y 

को देखते हुए बाद से गैर सख्त तर्क second द्वारा मूल्यांकन नहीं किया जाता है, undefined में गुजर एक समस्या का कारण नहीं है:

> second (Foo undefined 1) 
1 

लेकिन सख्त तर्क undefined नहीं किया जा सकता है, भले ही हम मूल्य का उपयोग नहीं करते हैं:

> first (Foo 1 undefined) 
*** Exception: Prelude.undefined 
+0

यह कर्ट सैम्पसन के उत्तर से बेहतर है क्योंकि यह वास्तव में आंतरिक कार्यान्वयन विवरणों को हटाने के बजाय, '!' प्रतीक के उपयोगकर्ता-देखने योग्य प्रभावों को समझाता है। –