2010-07-08 17 views
8

मेरे पास निम्न फ़ंक्शन परिभाषित किया गया है:यह हास्केल स्टेटमेंट आलसी मूल्यांकन क्यों नहीं करता है?

ex 1 x = 1 
ex 0 x = 0 
ex b x = b ** x 

फिर, जब मैं निम्न निष्पादित करता हूं:

1 `ex` (sum [1..]) 

यह आलसी होने और लौटने की बजाय अनंत अनुक्रम के योग की गणना करने का प्रयास करता है। क्यों ?


संपादित करें: आगे की जांच के बाद, मैंने पाया कि आलसी तब होती है जब मैं एक फ़ाइल में ex फ़ंक्शन को परिभाषित करता हूं, लेकिन यदि मैं इसे जीएचसीआई में परिभाषित नहीं करता हूं:

$ ghci 
GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help 
Loading package base ... linking ... done. 
Prelude> let ex 1 x = 1 
Prelude> let ex b x = b ** x 
Prelude> ex 1 (sum [1..]) 
<interactive>: out of memory (requested 1048576 bytes) 

अगर मैं ex परिभाषा खींचता हूं एक फ़ाइल में (इस मामले में, test.hs):

$ ghci 
GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help 
Loading package base ... linking ... done. 
Prelude> :load test.hs 
[1 of 1] Compiling Main    (test.hs, interpreted) 
Ok, modules loaded: Main. 
*Main> ex 1 (sum [1..]) 
1.0 

नया प्रश्न, तो, क्यों है?

+1

नहीं, 1 'ex' (sum [1 ..]) मेरे कंप्यूटर पर 1.0 लौटाता है। Ghc आदि का संस्करण क्या है? और क्या आपको पूर्व 1 (योग [1 ..]) के साथ एक ही परिणाम मिलता है? – ShreevatsaR

+1

संभवतः एक बग? –

+0

@ShreevatsaR: अच्छे अंक, ऊपर मेरा अपडेट देखें। – perimosocordiae

उत्तर

17

GHCi में है, प्रत्येक let बयान ex के नई परिभाषा, कई पैटर्न मामलों के बजाय आपकी अपेक्षा के परिचय देता है। तो यह लटकता है क्योंकि, जब आप ex 1 (sum [1..]) दर्ज करते हैं, तो केवल अंतिम ex b x = b ** x संस्करण मौजूद है।

आप GHCi में एक से अधिक पैटर्न मामलों के साथ एक समारोह को परिभाषित करना चाहते हैं, तो आप एक एकल let बयान में यह डाल करने के लिए इस तरह की आवश्यकता होगी:

let ex 1 x = 1; ex 0 x = 0; ex b x = b ** x 

ही कुछ और है कि सामान्य रूप से लागू होता है के लिए do नोटेशन जैसे कई लाइनों में लिखा जाना चाहिए। उदाहरण के लिए, इस तरह एक समारोह:

f x = do 
    y <- get 
    put (x + y) 
    return y 

GHCi में इस तरह लिखा होना होगा:

let f x = do { y <- get; put (x + y); return y } 
+0

आह, यह वास्तव में असुविधाजनक है। जानना अच्छा है, धन्यवाद, धन्यवाद! – perimosocordiae

+6

@perimosocordiae: जीएचसीआई के काफी भारी उपयोगकर्ता के रूप में, मैंने आम तौर पर बाहरी फाइल में अपनी सभी परिभाषाओं को लिखने, जीएचसीआई के साथ फाइल लोड करने और सरल अभिव्यक्तियों का मूल्यांकन करने के लिए आरईपीएल का उपयोग करने की आदत ली है। –

+2

आप कई पंक्तियों पर परिभाषा लिखने के लिए ': set + m' का भी उपयोग कर सकते हैं। – aleator

-2

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


क्योंकि sum अनुक्रम में सभी तत्वों के कुल योग गणना करता है। जो आपके मामले में अंतहीन है।

आप शायद चाहते

map ((curry ex) 1) [1..] 

map -- map each item x to y 
    (
     (
      curry ex -- curry ex, to transform (x, y) -> z into x -> y -> z 
     ) 
     1 -- then invoke it with 1, which results in y -> z, x being 1 
    ) 
    [1..] -- the infinite sequence to be mapped. 
+0

एचएम, मुझे नहीं लगता कि यह है। ऊपर मेरा अपडेट देखें। – perimosocordiae

+0

दंडित अद्यतन। हाँ, अब स्पष्ट है कि मुद्दा क्या है। – Dykam

+0

-1: अगर यह वास्तव में आवश्यक था तो यह केवल योग का मूल्यांकन करेगा, और इस मामले में यह नहीं था। – Zifre

1
Prelude> let ex 1 x = 1 
Prelude> let ex b x = b ** x 

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

एक पैटर्न को दो पैटर्न के साथ परिभाषित करने के लिए let ex 1 x = 1; ex b x = b ** x का उपयोग करें, यानी मामलों को अर्धविराम से अलग करें।

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