2015-09-14 6 views
15

जब मैं निम्नलिखित कोड है:हैस्केल में 'कहां' खंड में कुछ केवल एक बार गणना की जाती है?

func n = m ++ [1] ++ m ++ [0] ++ m 
    where m = func2 n 

कितनी बार func2 समारोह कहा जाता है? केवल एक बार, जहां खंड में? या जब मैं एम का उपयोग करता हूं तो क्या यह फिर से गणना की जाती है?

उत्तर

18

शायद यह सब (आलस्य की खुशी) पर मूल्यांकन नहीं है - लेकिन अगर ऐसा है, यह केवल एक बार मूल्यांकन किया जाना चाहिए - अगर आप चाहें, तो आप trace साथ खुद के लिए कोशिश कर सकते हैं:

import Debug.Trace(trace) 

func n = m ++ [1] ++ m ++ [0] ++ m 
    where m = func2 n 

func2 n = trace "called..." [n] 

यहाँ है GHCi में एक उदाहरण:

λ> func 3 
called... 
[3,1,3,0,3] 

और यहाँ एक है जहाँ आप देखते हैं कि यह कहा जाता है नहीं हो सकता है (जब तक आप अंततः यह मूल्यांकन करने की जरूरत):

λ> let v = func 4 

λ> v 
called... 
[4,1,4,0,4] 

देखें: पहले इसे नहीं कहा जाता है - केवल तभी जब आप अंततः v (इसे प्रिंट करने के लिए) का मूल्यांकन करते हैं तो आपको कॉल मिलता है।

8

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

{-# LANGUAGE NoMonomorphismRestriction #-} 

import Debug.Trace(trace) 

func n = m ++ [1] ++ m ++ [0] ++ m 
    where m = func2 n      -- m :: Monad t => t a (where n :: a) 

func2 n = trace "called..." (return n) -- func2 :: Monad t => a -> t a 

फिर GHCi प्रिंट में func 3 का मूल्यांकन

called... 
[3,1called... 
,3,0called... 
,3] 
+0

धन्यवाद - बहुत अच्छा मुद्दा - मैंने वास्तव में यहां इस बारे में नहीं सोचा था। जब इस तरह के विवरणों की बात आती है तो हास्केल पर सही उत्तर देना वास्तव में कठिन होता है - आमतौर पर एक ऐसा एक्सटेंशन होता है जो आपके अंतर्ज्ञान को बेकार करता है: * ( – Carsten

3

@ करने के लिए जोड़ने के लिए Carstan की और @Reid बार्टन के जवाब है, यह भी है या नहीं, आप चल रहे हैं, कोड या नहीं संकलित पर निर्भर करता है जैसे:

{-# LANGUAGE NoMonomorphismRestriction #-} 

import Debug.Trace(trace) 

func n = m ++ [1] ++ m ++ [0] ++ m 
    where m = func2 n      -- m :: Monad t => t a (where n :: a) 

func2 n = trace "called..." (return n) 

main = let xs = func 3 :: [Int] 
     in print xs 

ghcimaincalled 3 बार प्रिंट करता है। संकलित होने पर, -O2 का उपयोग करते समय, यह केवल called प्रिंट करता है। (7.10.2 के साथ परीक्षण किया गया।)

+0

क्या आप ऑप्टिमाइज़ेशन सक्षम हैं? मेरे पास केवल 7.10.1 है, लेकिन मुझे 'कॉल' दिखाई देता है 'संकलित होने पर 3 बार मुद्रित किया गया है। लेकिन निश्चित रूप से अनुकूलन सामान्य रूप से इस व्यवहार को भी प्रभावित कर सकते हैं। –

+0

हां - मैं -ओ 2 के साथ संकलित कर रहा था। मैं जवाब को स्पष्ट करूंगा। – ErikR

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