कैसे कई लाइनों में ghci में एक समारोह को परिभाषित करने के लिए?


161

मैं किसी भी सरल फ़ंक्शन को परिभाषित करने की कोशिश कर रहा हूं, जो ghci में कई लाइनों को फैलाता है, निम्नलिखित को एक उदाहरण के रूप में लें:

let abs n | n >= 0 = n
          | otherwise = -n

अब तक मैंने पहली पंक्ति के बाद Enter दबाने की कोशिश की है:

Prelude> let abs n | n >= 0 = n
Prelude>           | otherwise = -n
<interactive>:1:0: parse error on input `|'

मैं भी का उपयोग करने का प्रयास किया :{और :}आदेशों लेकिन मैं अब तक नहीं मिलता है:

Prelude> :{
unknown command ':{'
use :? for help.

मैं लिनक्स पर Haskell 98 के लिए GHC इंटरएक्टिव संस्करण 6.6 का उपयोग कर रहा हूं, मुझे क्या याद आ रहा है?


20
कृपया अपनी GHC स्थापना को अपग्रेड करें। GHC 6.6 की आयु लगभग 5 वर्ष है! हास्केल के नवीनतम संस्करण यहाँ हैं: haskell.org/platform
डॉन स्टीवर्ट


1
@ मर्क इस ओपी ने पहले ही उस समस्या के समाधान की कोशिश की। यह समस्या बाहर की घिसी-पिटी के कारण होती है, ज्ञान की कमी नहीं है कि क्या करना है। यहाँ समाधान: उन्नयन वहाँ समाधान: उपयोग :{, :}
एंड्रयूसी

जवाबों:


124

गार्ड्स के लिए (अपने उदाहरण की तरह), आप बस उन सभी को एक पंक्ति में रख सकते हैं और यह काम करता है (गार्ड को रिक्ति की परवाह नहीं है)

let abs n | n >= 0 = n | otherwise = -n

यदि आप अपने फ़ंक्शन को कई परिभाषाओं के साथ लिखना चाहते हैं, जो पैटर्न पर तर्कों से मेल खाते हैं, जैसे:

fact 0 = 1
fact n = n * fact (n-1)

तब आप परिभाषाओं को अलग करने वाले अर्धविराम वाले ब्रेसिज़ का उपयोग करेंगे

let { fact 0 = 1 ; fact n = n * fact (n-1) }

258

GHCi में अब एक बहु-इनपुट-इनपुट मोड है, जो इसके साथ सक्षम है: set + m। उदाहरण के लिए,

Prelude> :set +m
Prelude> let fac 0 = 1
Prelude|     fac n = n * fac (n-1)
Prelude|
Prelude> fac 10
3628800

39
मल्टीलाइन मोड सेट करना ghciइस संबंध में पायथन दुभाषिया की तरह व्यवहार करता है । बहुत ही सुविधाजनक! आप वास्तव .ghciमें अपने घर निर्देशिका में एक फ़ाइल बना सकते हैं जिसमें आप डालते हैं :set +mऔर हर बार शुरू होने पर मल्टीलाइन मोड डिफ़ॉल्ट हो जाएगा ghci!
21

2
यह वाकई कमाल है। लेकिन मैंने देखा है कि जब मैंने इसके बजाय :set prompt "λ "जारी लाइनों का उपयोग करके अपना संकेत सेट किया । किसी भी तरह से यह चारों ओर पाने के लिए? Preludeλ
अब्बलमैन

2
पैच के लिए एक नई निरंतरता शीघ्र परिभाषित करने के लिए यहां देखें ghc.haskell.org/trac/ghc/ticket/7509#no1
karakfa

4
निरंतरता की रेखाओं पर दिखाई देने वाली प्रस्तावना को रोकने के लिए, अपने .ghci में प्रॉम्प्ट 2 "|" |
निक

12
एक अनुगामी का उपयोग करके आप इंडेंटेशन से पूरी तरह से बच सकते हैं let। बस letएक newline द्वारा पीछा टाइप करें : leta। तब fac 0 = 1⏎। तब fac n = n * fac (n-1)⏎ ⏎ और आपका काम हो गया!
आइसलैंड_जैक

62

दान सही है, लेकिन :{और :}प्रत्येक की अपनी लाइन पर प्रकट करना चाहिए:

> :{ 
> let foo a b = a +
>           b
> :}
> :t foo
foo :: (Num a) => a -> a -> a

यह लेआउट नियम के साथ भी बातचीत करता है, इसलिए डू-नोटेशन का उपयोग करते समय स्पष्ट रूप से ब्रेसिज़ और अर्ध-कॉलोन का उपयोग करना आसान हो सकता है। उदाहरण के लिए, यह परिभाषा विफल होती है:

> :{
| let prRev = do
|   inp <- getLine
|   putStrLn $ reverse inp
| :}
<interactive>:1:18:
    The last statement in a 'do' construct must be an expression

लेकिन यह तब काम करता है जब ब्रेसिज़ और सेमी-कॉलन जोड़े जाते हैं:

> :{
| let prRev = do {
|   inp <- getLine;
|   putStrLn $ reverse inp;
| }
| :}
> :t prRev
prRev :: IO ()

यह वास्तव में केवल तभी महत्वपूर्ण होगा जब किसी फ़ाइल से परिभाषाओं को चिपकाया जाए, जहां इंडेंटेशन बदल सकता है।


यदि आपके पास '=' में समाप्त होने वाली रेखा नहीं है (अगली पंक्ति के बाद की परिभाषा के साथ), तो कम से कम 7.6.3 संस्करण में।
एडमेक

1
शायद यह विफल हो जाता है, क्योंकि दूसरी और तीसरी पंक्ति को पर्याप्त रूप से इंडेंट नहीं किया जाता है ...? (दो और रिक्त स्थान।)
Evi1M4chine


7

यदि आप जीएचसी को सिर्फ :{और सिर्फ अपग्रेड नहीं करना चाहते हैं :}, तो आपको यह सब एक लाइन पर लिखना होगा:

> let abs' n | n >= 0 = n | otherwise = -n

मैं हास्केल में किसी भी एक परिभाषा से अवगत नहीं हूं जो कई लाइनों पर लिखी जानी चाहिए। उपरोक्त GHCi में वास्तव में काम करता है:

> :t abs'
abs' :: (Num a, Ord a) => a -> a

अन्य अभिव्यक्तियों के लिए, जैसे कि doब्लॉक, आपको घुंघराले ब्रेसिज़ और सेमीकोलन (यूरोप) के साथ गैर-लेआउट सिंटैक्स का उपयोग करने की आवश्यकता होगी।


0

मैं GHCi का उपयोग कर रहा हूं, macOS Catalina 10.15.2 पर संस्करण 8.2.1। निम्नलिखित यह है कि कैसे मैं फ़ंक्शन प्रकार की घोषणा और गार्ड दोनों को एक साथ रखता हूं। नोट बाईं ओर ऊर्ध्वाधर पट्टियाँ जीएचसीआई कई लाइनों के लिए हैं।

λ: let abs' :: (Num a, Ord a) => a -> a
 |     abs' n | n >= 0 = n | otherwise = -n
 | 
λ: abs' 7
7
λ: abs' (-7)
7

1
यदि आप उपयोग करते हैं :{और :}आपको let अपने प्रकार की घोषणा से पहले निर्दिष्ट करने की आवश्यकता नहीं है , तो इसका मतलब है कि आपको दूसरी और बाद की लाइनों को इंडेंट करने की आवश्यकता नहीं है।
davidA

आपका बहुत बहुत धन्यवाद। यह वही है जो मैं ढूंढ रहा था लेकिन खोजने में असफल रहा।
गोल्डन थम्ब

0

ऐसा लगता है कि एक ही बार में दोनों पंक्तियों को चिपकाने या प्रत्येक नई लाइन के लिए नियंत्रण-प्रवेश का उपयोग करने से यह सब एक साथ रहता है, कम से कम https://repl.it/languages/haskell पर । दूसरी पंक्ति की शुरुआत में आपको 2 डॉट्स दिखाई देंगे। या इसे एक फ़ाइल में डालें और: फ़ाइल लोड करें (: l मुख्य)। कैसे आओ नकारात्मक संख्या के साथ काम नहीं करता है? ओह आपको संख्या के चारों ओर कोष्ठक लगाना होगा।

   let abs n | n >= 0 = n 
..           | otherwise = -n
   abs (-1)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.