2016-06-26 8 views
7

मैं हास्केल में अपरिवर्तनीय चर की अवधारणा के साथ काफी उलझन में हूं। ऐसा लगता है कि हम हास्केल में चर के मान को नहीं बदल सकते हैं। लेकिन जब मैं GHCi में कोड निम्नलिखित की कोशिश की, ऐसा लग रहा था चर के मूल्य की तरह बदलने के लिए क्या किया:हास्केल में अपरिवर्तनीय चर क्या है?

Prelude> foo x=x+1 
Prelude> a=1 
Prelude> a 
1 
Prelude> foo a 
2 
Prelude> a=2 
Prelude> a 
2 
Prelude> foo a 
3 

अपरिवर्तनीय चर के विचार के साथ इस विरोध है?

बहुत धन्यवाद!

+1

जो मेरे रैपल में काम नहीं करता है ... – Netwave

+0

'a = 1 डालने का प्रयास करें; एक = 2' '.hs' फ़ाइल के अंदर और इसे' ghc' के साथ संकलित करें ... – Bakuriu

+8

जीएचसीआई कमांड आईओ क्रियाएं हैं, इसलिए ऐसा लगता है कि आपके द्वारा टाइप की गई हर चीज 'डू' ब्लॉक के अंदर थी। जिसका अर्थ है कि उसी नाम के बाद के असाइनमेंट नेस्टेड 'चलो, आप * छाया * पुरानी बाध्यकारी की तरह हैं। – Bakuriu

उत्तर

18

हास्केल आपको मौजूदा चर को संशोधित करने की अनुमति नहीं देता है। हालांकि, यह आपको वैरिएबल नामों का पुन: उपयोग करने की अनुमति देता है, और यह सब कुछ हो रहा है। एक तरीका यह देखने के लिए GHCi पूछने के लिए, :i[nfo] निर्देश, जहां चर घोषित किया गया था का उपयोग कर रहा है:

Prelude> let a = 1 
Prelude> :i a 
a :: Num a => a  -- Defined at <interactive>:2:5 
Prelude> let a = 2 
Prelude> :i a 
a :: Num a => a  -- Defined at <interactive>:4:5 

ये वास्तव में दो पूरे अलग, अलग चर, जो सिर्फ एक ही नाम के नाम से जाना हो रहे हैं! तुम सिर्फ a के लिए कहते हैं, तो नए परिभाषा हो जाएगा “ वरीय ”, लेकिन जैसा कि टिप्पणी में ची ने टिप्पणी की एक पुरानी अभी भी वहाँ – एक तरह से यह देखने के लिए, एक समारोह में a उपयोग करने के लिए है:

Prelude> let a = 2 
Prelude> :i a 
a :: Num a => a  -- Defined at <interactive>:4:5 
Prelude> let f x = a + x 
Prelude> let a = 3 
Prelude> f (-2) 
0 

f को कभी भी यह ध्यान देने की आवश्यकता नहीं है कि आपने एक नया चर परिभाषित किया है जिसे a भी कहा जाता है; इसके परिप्रेक्ष्य से a एक अपरिवर्तनीय चर था जो हमेशा रहता है।


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

a = 1 
a = 2 

main :: IO() 
main = print a 

कारण यह है कि कुछ इस तरह GHCi में अनुमति दी है कि यह हास्केल मॉड्यूल से अलग काम करता है। जीएचसीआई आदेशों का अनुक्रम वास्तव में आईओ मोनैडऔर डैगर में कार्यों का अनुक्रम बनाता है;; यानी कार्यक्रम अब

main :: IO() 
main = do 
    let a = 1 
    let a = 2 
    print a 

होना चाहिए था, अगर आप monads के बारे में सीखा है आपको पता चल जाएगा कि इस के लिए

main = 
    let a = 1 in (let a = 2 in (print a)) 

बस वाक्यात्मक चीनी है और यह वास्तव में क्यों के लिए महत्वपूर्ण बिट है आप a नाम का पुनः उपयोग कर सकते हैं: दूसरा, a = 2, को पहले की तुलना में एक संक्षिप्त दायरे में रहता है। तो यह अधिक स्थानीय है, और स्थानीय परिभाषाओं को प्राथमिकता है।चाहे यह एक अच्छा विचार है थोड़ा बहस योग्य है; इसके लिए एक अच्छा तर्क आप की तरह

greet :: String -> IO() 
greet name = putStrLn $ "Hello, "++name++"!" 

एक कार्य हो सकता है और यह काम कर रहा है सिर्फ इसलिए किसी को कहीं और

name :: Car -> String 
name car | rollsOverAtRightTurn car = "Reliant Robin" 
     | fuelConsumption car > 50*litrePer100km 
             = "Hummer" 
     | ...      = ... 

इसके अलावा परिभाषित करता है बंद नहीं होगा कि है, यह वास्तव में बहुत उपयोगी है कि आप “ को फिर से परिभाषित कर सकते हैं ” जीएचसीआई में चारों ओर बेवकूफ बनाते समय चर, भले ही यह एक उचित कार्यक्रम में सामान को फिर से परिभाषित करने के लिए एक अच्छा विचार है, जो लगातार व्यवहार दिखाना है।


और डैगर; जैसा कि डेफ्यूयर टिप्पणी करता है, यह पूरी सच्चाई नहीं है। आप जीएचसीआई में कुछ चीजें कर सकते हैं जिन्हें IO डू-ब्लॉक में अनुमति नहीं है, विशेष रूप से आप data प्रकार और class es परिभाषित कर सकते हैं। लेकिन किसी भी सामान्य कथन या चर परिभाषा अधिनियम के रूप में यह IO monad में थे।

+0

एक चीज़ गायब है: जीएचसीआई 'डेटा', 'न्यूटाइप', 'टाइप',' क्लास 'और' इंस्टेंस 'घोषणाओं की अनुमति देता है, जिन्हें हास्केल' डू 'सिंटैक्स में अनुमति नहीं है। – dfeuer

+1

यह देखते हुए कि जीएचसीआई एक * इंटरैक्टिव * पर्यावरण है, यह एक आवश्यक विशेषता है। परिभाषा को गलत टाइप करने के लिए कितनी बार ऐसा हुआ? यदि आप हर बार ऐसा करते हैं तो आपको एक बिल्कुल नया नाम चुनना होगा, तो आप आसानी से 'myFunction7' जैसे अपठनीय नामों के साथ समाप्त हो जाएंगे, जहां' myFunction' की सभी पिछली परिभाषा में एक त्रुटि है, और आपको हमेशा उस '7' को जोड़ना याद रखना होगा सही परिभाषा का उपयोग ... – Bakuriu

+0

सही। यदि यह आवश्यक था तो हमें स्पष्ट रूप से अलग-अलग वर्कफ़्लो को अनुकूलित करने की आवश्यकता होगी, शायद स्पष्ट स्कॉइंग के साथ कुछ। – leftaroundabout

0

(GHCi का उपयोग अन्य जवाब ठीक है, लेकिन यह GHCi या monads के लिए विशिष्ट नहीं है स्पष्ट करने के लिए ...)

आप इस तथ्य से देख सकते हैं कि निम्नलिखित हास्केल कार्यक्रम

main = 
    let x = 1 in 
    let f y = x + y in 
    let x = 2 in 
    print (x * f 3) 

810 के बजाय प्रिंट करता है, चर केवल हास्केल में "उत्परिवर्तित" नहीं हो सकता है। दूसरे शब्दों में, कार्यक्रम के ऊपर बराबर है (बुलाया α-बराबर, बाध्य चर के नाम के अनुरूप परिवर्तन अर्थ केवल; अधिक जानकारी के लिए https://wiki.haskell.org/Alpha_conversion देखें)

main = 
    let x1 = 1 in 
    let f y = x1 + y in 
    let x2 = 2 in 
    print (x2 + f 3) 

जहां यह स्पष्ट है कि x1 और x2 विभिन्न चर हैं।

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