जीएचसीआई में मल्टी-लाइन कमांड


135

मुझे ghci में मल्टी-लाइन कमांड दर्ज करने में समस्या हो रही है।

निम्नलिखित 2-लाइन कोड एक फ़ाइल से काम करता है:

addTwo :: Int -> Int -> Int
addTwo x y = x + y

लेकिन जब मैं gci में प्रवेश करता हूं, मुझे एक त्रुटि मिलती है:

<interactive>:1:1: error:
    Variable not in scope: addTwo :: Int -> Int -> Int

मैंने कोड को अंदर डालने की भी कोशिश की :{ ... :}, लेकिन वे भी इस उदाहरण के लिए काम नहीं कर रहे हैं, क्योंकि यह सिर्फ एक पंक्ति में लाइनों को जोड़ रहा है, जो कि मामला नहीं होना चाहिए।

मैं WinGHCi, 2011.2.0.1 संस्करण का उपयोग कर रहा हूं


जवाबों:


184

ज्यादातर समय, आप अपने लिए एक हस्ताक्षर पर काम करने के प्रकार पर भरोसा कर सकते हैं। आपके उदाहरण में, निम्नलिखित पर्याप्त है:

Prelude> let addTwo x y = x + y

यदि आप वास्तव में एक प्रकार के हस्ताक्षर के साथ एक परिभाषा चाहते हैं, या आपकी परिभाषा कई लाइनों पर फैली हुई है, तो आप इसे ghci में कर सकते हैं:

Prelude> :{
Prelude| let addTwo :: Int -> Int -> Int
Prelude|     addTwo x y = x + y 
Prelude| :}
Prelude> addTwo 4 7
11

ध्यान दें कि आप इसे एक पंक्ति में भी निचोड़ सकते हैं:

Prelude> let addTwo :: Int -> Int -> Int ; addTwo x y = x + y

आप दस्तावेज़ीकरण के त्वरित अनुभाग में इंटरएक्टिव मूल्यांकन पर ghci के साथ बातचीत करने के बारे में अधिक जानकारी प्राप्त कर सकते हैं ।


1
दोनों के समाधान के लिए बहुत बहुत धन्यवाद। लेकिन मेरे पास एक और संबंधित प्रश्न है: दूसरी पंक्ति में (एडटू से पहले) चार प्रमुख रिक्तियां क्यों आवश्यक हैं? और यह सटीक होना चाहिए, यदि कम या अधिक खाली हैं, तो एक त्रुटि है।
R71

9
@ रॉग letशुरू होता है एक ब्लॉक; एक ब्लॉक में प्रविष्टियों को इंडेंटेशन द्वारा समूहीकृत किया जाता है; और एक ब्लॉक में पहला गैर-व्हाट्सएप चरित्र इंडेंटेशन सेट करता है जिसके द्वारा वे समूहीकृत होते हैं। चूँकि letऊपर के ब्लॉक में पहला नॉन-व्हाट्सएप कैरेक्टर है, इसलिए ब्लॉक aकी addTwoसभी लाइनों को उतना ही गहरा होना चाहिए a
डैनियल वैगनर

धन्यवाद। मैंने यह भी देखा कि अन्य में / जहां ब्लॉक। यह अन्य भाषाओं से एक बड़ा अंतर है जहां व्हाट्सएप को नजरअंदाज किया जाता है, इसलिए मुझे इसे समझने में थोड़ी कठिनाई हुई।
R71

125

GHCI और टाइपिंग करके इस समस्या को हल करें :set +m:

Prelude> :set +m
Prelude> let addTwo :: Int -> Int -> Int
Prelude|     addTwo x y = x + y
Prelude| 
Prelude> addTwo 1 3
4

बूम।


यहाँ क्या हो रहा है (और मैं ज्यादातर के लिए बात कर रहा हूँ आप , व्यक्ति की मदद के लिए googling जबकि माध्यम से अपने तरीके से काम कर जानें आप एक हास्केल ) कि GHCi एक इंटरैक्टिव वातावरण जहां मक्खी पर समारोह नामों की बाइंडिंग बदल रहे है। आपको अपनी फ़ंक्शन परिभाषाओं को एक letब्लॉक में लपेटना होगा , ताकि हास्केल को पता चले कि आप कुछ परिभाषित करने वाले हैं। :set +mसामान बहु के लिए आशुलिपि है :{ कोड :} निर्माण।

व्हाट्सएप ब्लॉकों में भी महत्वपूर्ण है, इसलिए आपको चार स्थानों के लिए अपने प्रकार की परिभाषा के बाद अपने फ़ंक्शन की परिभाषा को चार स्थानों के लिए खाते में इंडेंट करना होगा let


5
इतना सरल, लेकिन स्पष्ट नहीं। मैं उस पुस्तक पर चीखना चाहता था जिसका उपयोग मैं उस पृष्ठ 1 पर नहीं करने के लिए कह रहा था!
टिम

2
एक लिनक्स शेल से, echo ':set +m' >> ~/.ghciइस सेटिंग को लगातार बनाने के लिए।
truthadjustr

आप letपहली पंक्ति में स्वयं के पास हो सकते हैं, फिर बाकी सभी को बिल्कुल इंडेंट करने की आवश्यकता नहीं है। जहां व्हाट्सएप वास्तव में मायने रखता है वहां आपकी लाइनों पर रिक्त स्थान नहीं होना चाहिए। व्हाट्सएप को पीछे छोड़ते हुए एक अतिरिक्त दर्ज करें और मल्टी-लाइन ब्लॉक को तोड़ता है।
नेस


5

के रूप में GHCi संस्करण 8.0.1 , letअब आरईपीएल पर कार्यों को परिभाषित करने के लिए आवश्यक है।

तो यह आपके लिए ठीक काम करना चाहिए:

λ: addTwo x y = x + y
λ: addTwo 1 2
3
λ: :t addTwo
addTwo :: Num a => a -> a -> a

हास्केल का टाइप-इनफेरेंस सामान्यीकृत टाइपिंग प्रदान करता है जो फ्लोट के लिए भी काम करता है:

λ: addTwo 2.0 1.0
3.0

यदि आपको अपना स्वयं का टाइपिंग प्रदान करना है, तो ऐसा लगता है कि आपको मल्टीलाइन letइनपुट ( :set +mजीएचसीएल में मल्टीलाइन इनपुट सक्षम करने के लिए) का उपयोग करना होगा:

λ: let addTwo :: Int -> Int -> Int
 |     addTwo x y = x + y
 | 
λ: addTwo 1 2
3

लेकिन अगर आप Intअपने गैर-बहुरूपी टाइपिंग के कारण कुछ भी पास करने की कोशिश करते हैं, तो आपको त्रुटियाँ मिलेंगी :

λ: addTwo 2.0 1.0

<interactive>:34:8: error:
     No instance for (Fractional Int) arising from the literal 2.0
     In the first argument of addTwo’, namely 2.0
      In the expression: addTwo 2.0 1.0
      In an equation for it’: it = addTwo 2.0 1.0

2

हारून हॉल के उत्तर पर विस्तार करने के लिए , संस्करण जीएचसीआई 8.4.4 में कम से कम, आपको शैली का उपयोग letकरने पर टाइप घोषणाओं के साथ उपयोग करने की आवश्यकता नहीं :{ :}है। इसका मतलब है कि आपको खाते के लिए प्रत्येक बाद की लाइन पर 4-स्थान इंडेंटेशन जोड़ने के बारे में चिंता करने की ज़रूरत नहीं है let, जिससे लंबे कार्यों को टाइप करना आसान हो जाता है, या कई मामलों में, कॉपी-पेस्ट (क्योंकि मूल स्रोत की संभावना नहीं होगी) सही इंडेंटेशन):

λ: :{
 | addTwo :: Int -> Int -> Int
 | addTwo x y = x + y
 | :}
λ: addTwo 1 2
3

अपडेट करें

एक विकल्प के रूप में आप मल्टी-लाइन इनपुट मोड को चालू कर सकते हैं :set +m, फिर letअपने आप टाइप करें, एंटर दबाएं, फिर बिना किसी इंडेक्सेशन के साथ परिभाषाएँ पेस्ट करें।

हालाँकि यह कुछ कोड ब्लॉक के साथ काम नहीं करता है, जैसे:

class Box a where
  mkBox :: a -> Boxes.Box

लेकिन :{, :}तकनीक है।


1
वास्तव में, पहले भी, आप टाइप कर सकते हैं :{, फिर अगली पंक्ति letमें स्वयं द्वारा, फिर अपनी परिभाषाओं को बिना किसी अतिरिक्त इंडेंटेशन के पेस्ट करें, फिर पास में :}। :) और मल्टी-लाइन इनपुट मोड सेट के साथ ( :set +m) आपको तब तक ब्रेसिज़ कमांड की आवश्यकता नहीं थी जब तक कोड लाइनों पर कोई अनुगामी स्थान नहीं थे।
विल नेस

आह, तो :set +mआप बस letअपनी लाइन पर उपयोग कर सकते हैं ? तो आप कर सकते हैं - यह अच्छा है। धन्यवाद।
Davida

हम्म, मुझे कुछ ऐसे मामले मिले हैं, जहां केवल टाइप करना letतो न्यूलाइन काम नहीं करता है। मेरा संपादन देखें।
शाम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.