$
संकेत कोष्ठकों की जगह के लिए जादू सिंटैक्स नहीं है। यह एक साधारण इंफिक्स ऑपरेटर है, हर तरह से ऑपरेटर +
है।
(xs)
की तरह एक ही नाम के आसपास कोष्ठक लाना हमेशा बस xs
करने के लिए बराबर है। तो अगर $
किया गया है, तो आपको वही त्रुटि मिल जाएगी।
let findKey key xs = snd . head . filter (\(k,v) -> key == k) + xs
तथ्य यह है कि नंबर पर +
काम करता है तो यह कोई मतलब नहीं है पर ध्यान न दें, और बस: कल्पना करना क्या हुआ अगर आप इस तरह के +
रूप में कुछ अन्य ऑपरेटर तुम वहाँ से परिचित हैं, था क्या होगा
कोशिश अभिव्यक्ति की संरचना के बारे में सोचें; कौन से नियमों को कार्यों के रूप में पहचाना जा रहा है, और तर्क के रूप में उन्हें कौन से नियम पारित किए जा रहे हैं।
वास्तव में, +
का उपयोग करके वास्तव में पार्स और टाइपशेक सफलतापूर्वक उपयोग करता है! (यह आपको बकवास प्रकार वर्ग की बाधाओं के साथ एक समारोह देता है, लेकिन यदि आप उन्हें पूरा करते हैं तो इसका मतलब कुछ है)। चलो के माध्यम से चलना कैसे इन्फ़िक्स ऑपरेटरों हल कर रहे हैं:
let findKey key xs = snd . head . filter (\(k,v) -> key == k) + xs
सर्वोच्च प्राथमिकता बात हमेशा सामान्य कार्य अनुप्रयोग है (बस एक दूसरे के बगल शब्द लिखना, कोई इन्फ़िक्स शामिल ऑपरेटरों के साथ)। यहां केवल एक उदाहरण है, filter
लैम्ब्डा परिभाषा पर लागू होता है। यही कारण है कि "का समाधान" हो जाता है, और जहाँ तक पार्स करने ऑपरेटरों के बाकी का संबंध है के रूप में एक उप अभिव्यक्ति हो जाता है:
let findKey key xs
= let filterExp = filter (\(k,v) -> key == k)
in snd . head . fileterExp + xs
अगले सर्वोच्च प्राथमिकता बात .
ऑपरेटर है। हमारे पास यहां से चुनने के लिए कई मिल गए हैं, सभी एक ही प्राथमिकता के साथ। .
सही सहयोगी है, इसलिए हम सबसे पहले सबसे पहले लेते हैं (लेकिन यह वास्तव में परिणाम को नहीं बदलेगा जिसे हम चुनते हैं, क्योंकि का एक सहयोगी ऑपरेशन है, लेकिन पार्सर को यह जानने का कोई तरीका नहीं है):
let findKey key xs
= let filterExp = filter (\(k,v) -> key == k)
dotExp1 = head . filterExp
in snd . dotExp1 + xs
ध्यान दें कि .
अपने बाएँ और दाएँ करने के लिए तुरंत मामले पकड़ा। यही कारण है कि प्राथमिकता बहुत महत्वपूर्ण है।वहाँ अभी भी एक .
बाईं, जो +
से अभी भी उच्च पूर्वता है, जिससे वह अगले जाता है:
let findKey key xs
= let filterExp = filter (\(k,v) -> key == k)
dotExp1 = head . filterExp
dotExp2 = snd . dotExp1
in dotExp2 + xs
और हम काम हो गया! +
में ऑपरेटरों की सबसे कम प्राथमिकता है, इसलिए यह अपने तर्कों को अंतिम रूप देता है, और पूरी अभिव्यक्ति में सबसे ज्यादा कॉल होने के बाद समाप्त होता है। ध्यान दें कि +
कम प्राथमिकता होने से xs
को "दावा" किया जा रहा है, जो किसी भी उच्च प्राथमिकता अनुप्रयोगों के बाईं ओर तर्क के रूप में है। और यदि उनमें से कोई भी कम प्राथमिकता थी, तो वे पूरी अभिव्यक्ति dotExp2 + xs
को तर्क के रूप में ले लेते थे, इसलिए उन्हें अभी भी xs
नहीं मिल सका; xs
(किसी भी इंफिक्स ऑपरेटर से पहले एक इंफिक्स ऑपरेटर डालने से) इसे बाएं से कुछ भी तर्क के रूप में दावा करने से रोकता है।
इस तथ्य में है वास्तव में उसी तरह है कि $
, इस अभिव्यक्ति में पार्स किया गया है क्योंकि .
और $
एक ही रिश्तेदार पूर्वता .
और +
है कि राशि के लिए हो; $
को बहुत कम प्राथमिकता के लिए डिज़ाइन किया गया है, इसलिए यह बाएं और दाएं से जुड़े लगभग किसी भी अन्य ऑपरेटरों के साथ इस तरह काम करेगा।
let findKey key xs = snd . head . filter (\(k,v) -> key == k) xs
सामान्य समारोह आवेदन पहले से चला जाता है:
अगर हम नहींfilter
कॉल और xs
के बीच एक इन्फ़िक्स ऑपरेटर रखूँ , तो यह क्या होता है। यहां हमारे पास एक-दूसरे के बगल में 3 शब्द हैं: filter
, (\(k,v) -> key == k)
, और xs
। समारोह आवेदन बाईं साहचर्य है, इसलिए हम पहले वाम-पंथी जोड़ी ले:
let findKey key xs
= let filterExp1 = filter (\(k,v) -> key == k)
in snd . head . filterExp1 xs
अभी भी एक और सामान्य आवेदन बाईं, जो अभी भी .
की तुलना में अधिक पूर्वता है है, तो हम ऐसा:
let findKey key xs
= let filterExp1 = filter (\(k,v) -> key == k)
filterExp2 = filterExp1 xs
in snd . head . filterExp2
अब पहले डॉट:
let findKey key xs
= let filterExp1 = filter (\(k,v) -> key == k)
filterExp2 = filterExp1 xs
dotExp = head . filterExp2
in snd . dotExp
और हम काम हो गया, पूरी अभिव्यक्ति में सर्वोच्च कॉल इस समय सबसे बाईं ओर .
ऑपरेटर था। इस बार xs
को filter
पर दूसरे तर्क के रूप में चूसा गया; यह एक प्रकार है जहां हम चाहते हैं कि filter
दो तर्क लेता है, लेकिन यह filter
फ़ंक्शन संरचना श्रृंखला में छोड़ देता है, और filter
दो तर्कों पर लागू होता है, कोई फ़ंक्शन वापस नहीं कर सकता है। हम जो चाहते थे उसे एक पर फ़ंक्शन देने के लिए तर्क लागू करना था, यह फ़ंक्शन फ़ंक्शन संरचना श्रृंखला का हिस्सा हो, और उसके बाद संपूर्ण फ़ंक्शन xs
पर लागू करें।
वहाँ $
के साथ, अंतिम रूप दर्पण है कि जब हम +
प्रयोग किया है:
let findKey key xs
= let filterExp = filter (\(k,v) -> key == k)
dotExp1 = head . filterExp
dotExp2 = snd . dotExp1
in dotExp2 $ xs
यह वास्तव में जब हम +
था के रूप में एक ही तरह से पार्स है, इसलिए फर्क सिर्फ इतना है कि जहां +
का अर्थ है "अपने बाएं जोड़ने है मेरे दाहिने तर्क के लिए तर्क ", $
का अर्थ है" मेरे दाएं तर्क को मेरे दाएं तर्क में एक फ़ंक्शन के रूप में लागू करें "।हम यही करना चाहते थे! हुज़्ज़ाह!
TLDR: बुरी खबर है कि $
सिर्फ कोष्ठकों लपेटकर द्वारा काम नहीं करता है, यह उससे अधिक जटिल है। अच्छी खबर यह है कि यदि आप समझते हैं कि हास्केल इन्फ़िक्स ऑपरेटरों को शामिल भाव का समाधान करता है, तो आप कैसे $
काम करता है समझते हैं। जहां तक भाषा का संबंध है, इसके बारे में बिल्कुल कुछ भी नहीं है; यह एक साधारण ऑपरेटर है जिसे आप स्वयं परिभाषित कर सकते हैं यदि यह अस्तित्व में नहीं था।
(+)
जैसे किसी ऑपरेटर Parenthesising भी केवल आपके ठीक उसी समारोह +
से दर्शाया जाता है देता है, लेकिन अब यह विशेष इन्फ़िक्स वाक्य रचना नहीं है, तो यह प्रभावित करता है कि कैसे चीजों को इस मामले में पार्स किए जाते हैं । ऐसा नहीं है (xs)
जहां यह सिर्फ एक नाम है।
[Haskell: के बीच अंतर) के संभावित डुप्लिकेट। (डॉट) और $ (डॉलर चिह्न)] (http://stackoverflow.com/questions/940382/haskell-difference-between-dot-and-dollar-sign) – cdk