के बीच क्या अंतर है । (डॉट) और $ (डॉलर का चिह्न)?


709

बिंदी (.)और डॉलर के चिन्ह में क्या अंतर है ($)?

जैसा कि मैं इसे समझता हूं, वे दोनों कोष्ठक के उपयोग की आवश्यकता नहीं होने के लिए सिंटैक्टिक चीनी हैं।

जवाबों:


1226

$ऑपरेटर कोष्ठकों से बचने के लिए है। इसके बाद आने वाली कोई भी चीज पहले आने वाली किसी भी चीज पर वरीयता लेगी।

उदाहरण के लिए, मान लें कि आपको एक पंक्ति मिल गई है जिसमें लिखा है:

putStrLn (show (1 + 1))

यदि आप उन कोष्ठकों से छुटकारा पाना चाहते हैं, तो निम्नलिखित में से कोई भी एक ही काम करेगा:

putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1

.ऑपरेटर का प्राथमिक उद्देश्य कोष्ठकों से बचना नहीं है, बल्कि श्रृंखला कार्यों के लिए है। यह आपको बाईं ओर दिखाई देने वाले इनपुट के दाईं ओर दिखाई देने वाले आउटपुट को टाई करने देता है। यह आमतौर पर कम कोष्ठक में परिणाम करता है, लेकिन अलग तरह से काम करता है।

उसी उदाहरण पर वापस जा रहे हैं:

putStrLn (show (1 + 1))
  1. (1 + 1)इनपुट नहीं है, और इसलिए .ऑपरेटर के साथ इसका उपयोग नहीं किया जा सकता है ।
  2. showएक ले सकते हैं Intऔर एक वापस कर सकते हैं String
  3. putStrLnएक ले सकते हैं Stringऔर एक वापस कर सकते हैं IO ()

आप इसे पसंद showकरने के लिए चेन कर सकते हैं putStrLn:

(putStrLn . show) (1 + 1)

यदि आपकी पसंद के लिए बहुत अधिक कोष्ठक हैं, तो उन्हें $ऑपरेटर से छुटकारा दिलाएं:

putStrLn . show $ 1 + 1

54
दरअसल, चूँकि + एक फ़ंक्शन भी है, इसलिए आप इसे पहले से जोड़कर नहीं बना सकते हैं और फिर इसे 'putStrLn' की तरह बना सकते हैं। प्रदर्शन । (+) 1 1 `ऐसा नहीं है कि यह कोई स्पष्ट है, लेकिन मेरा मतलब है ... आप कर सकते हैं, है ना?
कोडेक्सआर्कनम

4
@CodexArcanum इस उदाहरण में, कुछ समान putStrLn . show . (+1) $ 1होगा। आप उस सबसे (सभी?) इन्फिक्स ऑपरेटरों के कार्य सही हैं।
माइकल स्टील

79
मुझे आश्चर्य है कि क्यों कोई भी कभी भी उल्लेख का उपयोग नहीं करता है map ($3)। मेरा मतलब है, मैं ज्यादातर $कोष्ठक से बचने के लिए उपयोग करता हूं , लेकिन ऐसा नहीं है कि वे सभी के लिए हैं।
घन

43
map ($3)प्रकार का एक कार्य है Num a => [(a->b)] -> [b]। यह एक संख्या लेने वाले कार्यों की एक सूची लेता है, उन सभी पर 3 लागू करता है और परिणाम एकत्र करता है।
घन

21
अन्य ऑपरेटरों के साथ $ का उपयोग करते समय आपको सावधान रहना होगा। "x + f (y + z)" "x + f $ y + z" के समान नहीं है क्योंकि उत्तरार्द्ध वास्तव में इसका मतलब है "(x + f) (y + z)" (यानी x और f का योग) एक समारोह के रूप में माना जाता है)।
पॉल जॉन्सन

186

उनकी विभिन्न प्रकार और विभिन्न परिभाषाएँ हैं:

infixr 9 .
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)

infixr 0 $
($) :: (a -> b) -> a -> b
f $ x = f x

($)सामान्य फ़ंक्शन एप्लिकेशन को प्रतिस्थापित करने का इरादा है, लेकिन कोष्ठक से बचने में मदद करने के लिए एक अलग मिसाल पर। (.)एक नया कार्य करने के लिए एक साथ दो कार्यों की रचना के लिए है।

कुछ मामलों में वे विनिमेय हैं, लेकिन यह सामान्य रूप से सच नहीं है। विशिष्ट उदाहरण वे कहाँ हैं:

f $ g $ h $ x

==>

f . g . h $ x

दूसरे शब्दों में $, s की एक श्रृंखला में , लेकिन अंतिम एक को प्रतिस्थापित किया जा सकता है.


1
अगर xकोई फंक्शन होता तो क्या होता? क्या तब आप .अंतिम के रूप में उपयोग कर सकते हैं ?
रिचीज़

3
@richizy यदि आप वास्तव xमें इस संदर्भ में आवेदन कर रहे हैं , तो हाँ - लेकिन फिर "अंतिम" एक के अलावा किसी और चीज़ पर लागू होगा x। यदि आप आवेदन नहीं कर रहे हैं x, तो यह xमूल्य होने के लिए अलग नहीं है ।
जीएस -

124

यह भी ध्यान रखें कि ($)है पहचान समारोह प्रकार के लिए विशेष समारोह । पहचान समारोह इस तरह दिखता है:

id :: a -> a
id x = x

जबकि ($)इस तरह दिखता है:

($) :: (a -> b) -> (a -> b)
($) = id

ध्यान दें कि मैंने जानबूझकर टाइप सिग्नेचर में अतिरिक्त कोष्ठक जोड़े हैं।

($)आमतौर पर कोष्ठक (जब तक ऑपरेटर एक अनुभाग में उपयोग नहीं किया जाता है) को जोड़कर उपयोग को समाप्त किया जा सकता है। जैसे: f $ g xबन जाता है f (g x)

(.)प्रतिस्थापन के लिए उपयोग अक्सर थोड़ा कठिन होता है; उन्हें आमतौर पर एक लंबोदर या एक स्पष्ट फ़ंक्शन पैरामीटर की आवश्यकता होती है। उदाहरण के लिए:

f = g . h

हो जाता है

f x = (g . h) x

हो जाता है

f x = g (h x)

उम्मीद है की यह मदद करेगा!


"ध्यान दें कि मैंने जानबूझकर टाइप सिग्नेचर में अतिरिक्त कोष्ठक जोड़े हैं।" मैं उलझन में हूँ ... आप ऐसा क्यों करेंगे?
मतीन उल्हाक

3
@MateenUlhaq ($) का प्रकार (a -> b) -> a -> b है, जो कि (a -> b) -> (a -> b) के समान है, लेकिन अतिरिक्त कोष्ठक यहाँ कुछ करते हैं। स्पष्टता।
रूडी

2
ओह, मुझे लगता है। मैं इसे दो तर्कों के एक समारोह के रूप में सोच रहा था ... लेकिन करीने की वजह से, यह एक फ़ंक्शन के बराबर है जो एक फ़ंक्शन देता है।
मतीन उल्हाक

78

($) मूल्यांकन क्रम को नियंत्रित करने के लिए कोष्ठक को जोड़े बिना कार्यों को एक साथ जंजीर से जोड़ने की अनुमति देता है:

Prelude> head (tail "asdf")
's'

Prelude> head $ tail "asdf"
's'

रचना संचालक (.)तर्कों को निर्दिष्ट किए बिना एक नया फ़ंक्शन बनाता है:

Prelude> let second x = head $ tail x
Prelude> second "asdf"
's'

Prelude> let second = head . tail
Prelude> second "asdf"
's'

ऊपर दिया गया उदाहरण यकीनन निराशाजनक है, लेकिन वास्तव में रचना के उपयोग की सुविधा नहीं दिखाता है। यहाँ एक और सादृश्य है:

Prelude> let third x = head $ tail $ tail x
Prelude> map third ["asdf", "qwer", "1234"]
"de3"

यदि हम केवल एक बार तीसरे का उपयोग करते हैं, तो हम इसे लंबोदा का उपयोग करके नाम देने से बच सकते हैं:

Prelude> map (\x -> head $ tail $ tail x) ["asdf", "qwer", "1234"]
"de3"

अंत में, रचना हमें लंबोदर से बचने की सुविधा देती है:

Prelude> map (head . tail . tail) ["asdf", "qwer", "1234"]
"de3"

3
यदि स्टैकओवरफ़्लो में एक संयोजन फ़ंक्शन था, तो मैं इस उत्तर में पिछले दो स्पष्टीकरणों के उदाहरण के साथ संयोजन को पसंद करूंगा।
क्रिस .Q

59

लघु और मधुर संस्करण:

  • ($) फ़ंक्शन को कॉल करता है जो इसके बाएं हाथ के तर्क है जो इसके दाहिने हाथ का तर्क है।
  • (.) फ़ंक्शन को कंपोज़ करता है जो कि फ़ंक्शन पर उसका लेफ्ट-हैंड तर्क है जो उसका राइट-हैंड तर्क है।

29

एक अनुप्रयोग जो उपयोगी है और मुझे कुछ ही समय में यह जानने के लिए कि आपको एक हेकेल सीखना है :

f $ x = f x

और एक infix ऑपरेटर युक्त अभिव्यक्ति के दाहिने हाथ की ओर कोष्ठक बनाने से यह एक उपसर्ग फ़ंक्शन में परिवर्तित हो जाता है, जिससे कोई भी ($ 3) (4+)अनुरूप लिख सकता है (++", world") "hello"

कोई यह क्यूँ करेगा? उदाहरण के लिए, कार्यों की सूची के लिए। दोनों:

map (++", world") ["hello","goodbye"]`

तथा:

map ($ 3) [(4+),(3*)]

से छोटे हैं map (\x -> x ++ ", world") ...या map (\f -> f 3) ...। जाहिर है, बाद वाले संस्करण ज्यादातर लोगों के लिए अधिक पठनीय होंगे।


14
btw, मैं $3अंतरिक्ष के बिना उपयोग करने के खिलाफ सलाह देंगे । यदि टेम्पलेट हास्केल सक्षम है, तो यह एक ब्याह के रूप में पार्स किया जाएगा, जबकि $ 3हमेशा का अर्थ है कि आपने क्या कहा था। सामान्य तौर पर हस्केल में वाक्य रचना के बिट्स को "चुराने" का एक चलन लगता है कि यह सुनिश्चित करने के लिए कि कुछ ऑपरेटरों के पास उनके आसपास के रिक्त स्थान हैं जैसे कि उन्हें माना जाता है।
जीएस -

1
मुझे यह जानने में थोड़ा
Casebash

18

हास्केल: .(डॉट) और $(डॉलर चिह्न) के बीच अंतर

डॉट (.)और डॉलर के चिन्ह में क्या अंतर है ($)? जैसा कि मैं इसे समझता हूँ, वे दोनों कोष्ठक के उपयोग की आवश्यकता नहीं होने के लिए एक प्रकार की चीनी हैं।

वे हैं नहीं उपयोग कोष्ठकों करने की जरूरत नहीं करने के लिए वाक्यात्मक चीनी - वे काम करता है, कर रहे हैं - infixed, इस प्रकार हम उन्हें ऑपरेटरों कह सकते हैं।

रचना, (.)और इसका उपयोग कब करना है।

(.)रचना है। इसलिए

result = (f . g) x

एक फ़ंक्शन के निर्माण के समान है जो अपने तर्क के परिणाम को पास करता gहै f

h = \x -> f (g x)
result = h x

उपयोग करें (.)जब आपके पास उन कार्यों को पास करने के लिए तर्क उपलब्ध न हों जो आप रचना करना चाहते हैं।

सही साहचर्य लागू होता है, ($)और इसका उपयोग कब करना है

($)कम बाध्यकारी पूर्वता के साथ एक सही-सहयोगी अनुप्रयोग फ़ंक्शन है। इसलिए यह केवल चीजों को सबसे पहले इसके दाईं ओर गणना करता है। इस प्रकार,

result = f $ g x

यह इस तरह से है, प्रक्रियात्मक रूप से (जो हास्केल के आलसी के मूल्यांकन के बाद से मायने रखता है, यह fपहले मूल्यांकन करना शुरू करेगा ):

h = f
g_x = g x
result = h g_x

या अधिक संक्षेप में:

result = f (g x)

($)जब आप परिणाम के लिए पूर्ववर्ती फ़ंक्शन को लागू करने से पहले मूल्यांकन करने के लिए सभी चर का उपयोग करें ।

हम प्रत्येक फ़ंक्शन के स्रोत को पढ़कर इसे देख सकते हैं।

स्रोत पढ़ें

यहाँ के लिए स्रोत है (.):

-- | Function composition.
{-# INLINE (.) #-}
-- Make sure it has TWO args only on the left, so that it inlines
-- when applied to two functions, even if there is no final argument
(.)    :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)

और यहाँ के लिए स्रोत है ($):

-- | Application operator.  This operator is redundant, since ordinary
-- application @(f x)@ means the same as @(f '$' x)@. However, '$' has
-- low, right-associative binding precedence, so it sometimes allows
-- parentheses to be omitted; for example:
--
-- >     f $ g $ h x  =  f (g (h x))
--
-- It is also useful in higher-order situations, such as @'map' ('$' 0) xs@,
-- or @'Data.List.zipWith' ('$') fs xs@.
{-# INLINE ($) #-}
($)                     :: (a -> b) -> a -> b
f $ x                   =  f x

निष्कर्ष

रचना का उपयोग करें जब आपको फ़ंक्शन का तुरंत मूल्यांकन करने की आवश्यकता नहीं होती है। हो सकता है कि आप उस फ़ंक्शन को पास करना चाहते हैं जो रचना से दूसरे फ़ंक्शन में परिणाम करता है।

जब आप पूर्ण मूल्यांकन के लिए सभी तर्कों की आपूर्ति कर रहे हों तो एप्लिकेशन का उपयोग करें।

हमारे उदाहरण के लिए, ऐसा करना शब्दार्थ होगा

f $ g x

जब हमारे पास x(या बल्कि, gतर्क हैं), और करें:

f . g

जब हम नहीं।


12

... या आप पाइपलाइनिंग का उपयोग करके निर्माण .और $निर्माण से बच सकते हैं :

third xs = xs |> tail |> tail |> head

हेल्पर फंक्शन में शामिल होने के बाद:

(|>) x y = y x

2
हाँ, |> F # पाइपलाइन ऑपरेटर है।
user1721780 10

6
यहां एक बात ध्यान देने वाली है, कि हास्केल का $ऑपरेटर वास्तव में F # की तरह काम <|करता है |>, जैसे कि आमतौर पर haskell में आप ऊपर दिए गए फंक्शन को इस तरह से लिखते हैं: third xs = head $ tail $ tail $ xsया शायद पसंद भी करते हैं third = head . tail . tail, जो F # -स्टाइल सिंटैक्स में कुछ इस तरह होगा:let third = List.head << List.tail << List.tail
इलेक्ट्रिक कॉफी

1
हास्केल को F # की तरह बनाने के लिए एक सहायक फ़ंक्शन क्यों जोड़ें? -1
वाइकिंगस्टेव

9
फ़्लिप $पहले से उपलब्ध है, और इसे & hackage.haskell.org/package/base-4.8.0.0/docs/…
pat

11

किसी भी चीज़ (किसी फ़ंक्शन) के बारे में अधिक जानने का एक शानदार तरीका यह याद रखना है कि सब कुछ एक फ़ंक्शन है! यह सामान्य मंत्र मदद करता है, लेकिन ऑपरेटरों जैसे विशिष्ट मामलों में, यह इस छोटी सी चाल को याद रखने में मदद करता है:

:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c

तथा

:t ($)
($) :: (a -> b) -> a -> b

बस :tउदारतापूर्वक उपयोग करने के लिए याद रखें , और अपने ऑपरेटरों को इसमें लपेटें ()!


11

मेरा नियम सरल है (मैं बहुत शुरुआती हूं):

  • .यदि आप पैरामीटर (फ़ंक्शन को कॉल करें), और पास करना चाहते हैं, तो उपयोग न करें
  • $यदि कोई पैरामीटर अभी तक नहीं है तो उपयोग न करें (एक फ़ंक्शन लिखें)

अर्थात्

show $ head [1, 2]

लेकिन कभी नही:

show . head [1, 2]

3
अच्छा अनुमानी, लेकिन अधिक उदाहरणों का उपयोग कर सकता है
Zoey Hewll

0

मुझे लगता है कि आप कहां उपयोग करेंगे .और $किन चीजों को स्पष्ट करने में मदद नहीं करेंगे, इसका एक छोटा उदाहरण ।

double x = x * 2
triple x = x * 3
times6 = double . triple

:i times6
times6 :: Num c => c -> c

ध्यान दें कि times6एक ऐसा फंक्शन है जो फंक्शन कंपोजीशन से बनाया गया है।


0

अन्य सभी उत्तर बहुत अच्छे हैं। लेकिन इस बारे में एक महत्वपूर्ण प्रयोज्य विस्तार है कि ghc $ का व्यवहार कैसे करता है, कि ghc प्रकार चेकर उच्च श्रेणी / परिमाणित प्रकारों के साथ अस्थिरता की अनुमति देता है। यदि आप $ idउदाहरण के प्रकार को देखते हैं तो आप पाएंगे कि यह एक ऐसा फ़ंक्शन है जिसका तर्क स्वयं एक बहुरूपिक फ़ंक्शन है। समतुल्य परेशान ऑपरेटर के साथ उस तरह की छोटी चीजें समान लचीलापन नहीं दी जाती हैं। (यह वास्तव में मुझे आश्चर्यचकित करता है कि क्या $ एक ही उपचार के योग्य है या नहीं)

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