2016-11-28 4 views
7

जीएचसी 8 HasCallStackGHC.Stack मॉड्यूल से प्रदान करता है, जो फ़ंक्शन को अनुरोध करते समय रिकॉर्ड किए जाने वाले स्टैक फ्रेम का अनुरोध करने की अनुमति देता है। यह withFrozenCallStack फ़ंक्शन भी प्रदान करता है, जो कॉल स्टैक को "फ्रीज" करता है ताकि इसमें कोई और फ्रेम जोड़ा जा सके।FrozenCallStack के साथ उपयोग करते समय HasCallStack अभी भी स्टैक फ्रेम क्यों जोड़ता है?

सरल परिदृश्यों में, यह काम करता है जैसा कि मैं अपेक्षा करता हूं। उदाहरण के लिए:

ghci> let foo :: HasCallStack => CallStack 
      foo = callStack 
ghci> foo 
[("foo",SrcLoc {srcLocPackage = "interactive", srcLocModule = "Ghci2", srcLocFile = "<interactive>", srcLocStartLine = 8, srcLocStartCol = 1, srcLocEndLine = 8, srcLocEndCol = 4})] 
ghci> withFrozenCallStack foo 
[] 

जब मैं foo सामान्य रूप से कहते हैं, मैं एक ढेर फ्रेम मिलता है, लेकिन जब मैं withFrozenCallStack साथ लपेट, मुझे नहीं पता। उत्तम। ,

ghci> let foo :: CallStack 
      foo = bar 
      bar :: HasCallStack => CallStack 
      bar = callStack 
ghci> foo 
[("bar",SrcLoc {srcLocPackage = "interactive", srcLocModule = "Ghci9", srcLocFile = "<interactive>", srcLocStartLine = 24, srcLocStartCol = 11, srcLocEndLine = 24, srcLocEndCol = 14})] 
ghci> withFrozenCallStack foo 
[("bar",SrcLoc {srcLocPackage = "interactive", srcLocModule = "Ghci9", srcLocFile = "<interactive>", srcLocStartLine = 24, srcLocStartCol = 11, srcLocEndLine = 24, srcLocEndCol = 14})] 

अविवेक की इस सरल परत को जोड़ कर, स्टैक फ्रेम अभी भी शामिल हो जाता है withFrozenCallStack के अपने प्रयोग के बावजूद: हालांकि, जब उदाहरण केवल थोड़ा अधिक जटिल हो जाता है, यह व्यवहार कर बंद हो जाता है जैसे मैं उम्मीद करते हैं। क्यूं कर?

वैचारिक रूप से, HasCallStack की मेरी समझ यह वर्तमान कॉल स्टैक पर pushCallStack का एक अंतर्निहित उपयोग की तरह है कि है, और pushCallStack एक जमे हुए कॉल स्टैक पर कोई प्रभाव नहीं है। फिर, withFrozenCallStack कॉल स्टैक में उपरोक्त स्टैक फ्रेम को जोड़ने से क्यों नहीं रोकता है?

उत्तर

2

अपने कोड में, fooCallStack टाइप का एक स्थिर मान है। ध्यान दें कि यह पर HasCallStack बाधा है।

इससे कोई फ़र्क नहीं पड़ता कि आप foo का उपयोग कैसे करते हैं, यह हमेशा इस विशेष CallStack का संदर्भ देगा। इससे कोई फर्क नहीं पड़ता कि foo स्वयं bar का उपयोग करके परिभाषित किया गया है जो HasCallStack मशीनरी का उपयोग करता है - आप केवल foo = [("bar",… को स्थिर रूप से परिभाषित कर सकते हैं।

HasCallStack =>foo के प्रकार हस्ताक्षर जोड़ने का प्रयास करें। क्या अब आप जिस तरह से उम्मीद करते हैं उसका व्यवहार करते हैं?

+0

आह, ज़ाहिर है, यह समझ में आता है। हास्केल में अंतर्निहित मापदंडों के बारे में मेरा अंतर्ज्ञान स्पष्ट रूप से सबसे अच्छा नहीं है, क्योंकि यह किसी भी अंतर्निहित पैरामीटर पर लागू होगा, न कि केवल 'हैसकॉलस्टैक'। आपका धन्यावाद। –

+0

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

+0

आह, हाँ, यह समझ में आता है-आप फिर से सही हैं। :) 'HasCallStack' की जादुई प्रकृति निश्चित रूप से थोड़ा उलझन में है। मुझे अभी भी नहीं लगता कि मैं 'हैककॉलस्टैक' बाधाओं का अनुमान लगाता हूं, इसकी जटिलताओं को पूरी तरह से समझता हूं, लेकिन सौभाग्य से यह मेरे लिए अभ्यास में बहुत अधिक नहीं लगता है, हाहा। –

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