बिंदी (.)
और डॉलर के चिन्ह में क्या अंतर है ($)
?
जैसा कि मैं इसे समझता हूं, वे दोनों कोष्ठक के उपयोग की आवश्यकता नहीं होने के लिए सिंटैक्टिक चीनी हैं।
बिंदी (.)
और डॉलर के चिन्ह में क्या अंतर है ($)
?
जैसा कि मैं इसे समझता हूं, वे दोनों कोष्ठक के उपयोग की आवश्यकता नहीं होने के लिए सिंटैक्टिक चीनी हैं।
जवाबों:
$
ऑपरेटर कोष्ठकों से बचने के लिए है। इसके बाद आने वाली कोई भी चीज पहले आने वाली किसी भी चीज पर वरीयता लेगी।
उदाहरण के लिए, मान लें कि आपको एक पंक्ति मिल गई है जिसमें लिखा है:
putStrLn (show (1 + 1))
यदि आप उन कोष्ठकों से छुटकारा पाना चाहते हैं, तो निम्नलिखित में से कोई भी एक ही काम करेगा:
putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1
.
ऑपरेटर का प्राथमिक उद्देश्य कोष्ठकों से बचना नहीं है, बल्कि श्रृंखला कार्यों के लिए है। यह आपको बाईं ओर दिखाई देने वाले इनपुट के दाईं ओर दिखाई देने वाले आउटपुट को टाई करने देता है। यह आमतौर पर कम कोष्ठक में परिणाम करता है, लेकिन अलग तरह से काम करता है।
उसी उदाहरण पर वापस जा रहे हैं:
putStrLn (show (1 + 1))
(1 + 1)
इनपुट नहीं है, और इसलिए .
ऑपरेटर के साथ इसका उपयोग नहीं किया जा सकता है ।show
एक ले सकते हैं Int
और एक वापस कर सकते हैं String
।putStrLn
एक ले सकते हैं String
और एक वापस कर सकते हैं IO ()
।आप इसे पसंद show
करने के लिए चेन कर सकते हैं putStrLn
:
(putStrLn . show) (1 + 1)
यदि आपकी पसंद के लिए बहुत अधिक कोष्ठक हैं, तो उन्हें $
ऑपरेटर से छुटकारा दिलाएं:
putStrLn . show $ 1 + 1
putStrLn . show . (+1) $ 1
होगा। आप उस सबसे (सभी?) इन्फिक्स ऑपरेटरों के कार्य सही हैं।
map ($3)
। मेरा मतलब है, मैं ज्यादातर $
कोष्ठक से बचने के लिए उपयोग करता हूं , लेकिन ऐसा नहीं है कि वे सभी के लिए हैं।
map ($3)
प्रकार का एक कार्य है Num a => [(a->b)] -> [b]
। यह एक संख्या लेने वाले कार्यों की एक सूची लेता है, उन सभी पर 3 लागू करता है और परिणाम एकत्र करता है।
उनकी विभिन्न प्रकार और विभिन्न परिभाषाएँ हैं:
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 की एक श्रृंखला में , लेकिन अंतिम एक को प्रतिस्थापित किया जा सकता है.
x
कोई फंक्शन होता तो क्या होता? क्या तब आप .
अंतिम के रूप में उपयोग कर सकते हैं ?
x
में इस संदर्भ में आवेदन कर रहे हैं , तो हाँ - लेकिन फिर "अंतिम" एक के अलावा किसी और चीज़ पर लागू होगा x
। यदि आप आवेदन नहीं कर रहे हैं x
, तो यह x
मूल्य होने के लिए अलग नहीं है ।
यह भी ध्यान रखें कि ($)
है पहचान समारोह प्रकार के लिए विशेष समारोह । पहचान समारोह इस तरह दिखता है:
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)
उम्मीद है की यह मदद करेगा!
($)
मूल्यांकन क्रम को नियंत्रित करने के लिए कोष्ठक को जोड़े बिना कार्यों को एक साथ जंजीर से जोड़ने की अनुमति देता है:
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"
एक अनुप्रयोग जो उपयोगी है और मुझे कुछ ही समय में यह जानने के लिए कि आपको एक हेकेल सीखना है :
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) ...
। जाहिर है, बाद वाले संस्करण ज्यादातर लोगों के लिए अधिक पठनीय होंगे।
$3
अंतरिक्ष के बिना उपयोग करने के खिलाफ सलाह देंगे । यदि टेम्पलेट हास्केल सक्षम है, तो यह एक ब्याह के रूप में पार्स किया जाएगा, जबकि $ 3
हमेशा का अर्थ है कि आपने क्या कहा था। सामान्य तौर पर हस्केल में वाक्य रचना के बिट्स को "चुराने" का एक चलन लगता है कि यह सुनिश्चित करने के लिए कि कुछ ऑपरेटरों के पास उनके आसपास के रिक्त स्थान हैं जैसे कि उन्हें माना जाता है।
हास्केल:
.
(डॉट) और$
(डॉलर चिह्न) के बीच अंतरडॉट
(.)
और डॉलर के चिन्ह में क्या अंतर है($)
? जैसा कि मैं इसे समझता हूँ, वे दोनों कोष्ठक के उपयोग की आवश्यकता नहीं होने के लिए एक प्रकार की चीनी हैं।
वे हैं नहीं उपयोग कोष्ठकों करने की जरूरत नहीं करने के लिए वाक्यात्मक चीनी - वे काम करता है, कर रहे हैं - 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
जब हम नहीं।
... या आप पाइपलाइनिंग का उपयोग करके निर्माण .
और $
निर्माण से बच सकते हैं :
third xs = xs |> tail |> tail |> head
हेल्पर फंक्शन में शामिल होने के बाद:
(|>) x y = y x
$
ऑपरेटर वास्तव में F # की तरह काम <|
करता है |>
, जैसे कि आमतौर पर haskell में आप ऊपर दिए गए फंक्शन को इस तरह से लिखते हैं: third xs = head $ tail $ tail $ xs
या शायद पसंद भी करते हैं third = head . tail . tail
, जो F # -स्टाइल सिंटैक्स में कुछ इस तरह होगा:let third = List.head << List.tail << List.tail
किसी भी चीज़ (किसी फ़ंक्शन) के बारे में अधिक जानने का एक शानदार तरीका यह याद रखना है कि सब कुछ एक फ़ंक्शन है! यह सामान्य मंत्र मदद करता है, लेकिन ऑपरेटरों जैसे विशिष्ट मामलों में, यह इस छोटी सी चाल को याद रखने में मदद करता है:
:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
तथा
:t ($)
($) :: (a -> b) -> a -> b
बस :t
उदारतापूर्वक उपयोग करने के लिए याद रखें , और अपने ऑपरेटरों को इसमें लपेटें ()
!
मेरा नियम सरल है (मैं बहुत शुरुआती हूं):
.
यदि आप पैरामीटर (फ़ंक्शन को कॉल करें), और पास करना चाहते हैं, तो उपयोग न करें$
यदि कोई पैरामीटर अभी तक नहीं है तो उपयोग न करें (एक फ़ंक्शन लिखें)अर्थात्
show $ head [1, 2]
लेकिन कभी नही:
show . head [1, 2]
मुझे लगता है कि आप कहां उपयोग करेंगे .
और $
किन चीजों को स्पष्ट करने में मदद नहीं करेंगे, इसका एक छोटा उदाहरण ।
double x = x * 2
triple x = x * 3
times6 = double . triple
:i times6
times6 :: Num c => c -> c
ध्यान दें कि times6
एक ऐसा फंक्शन है जो फंक्शन कंपोजीशन से बनाया गया है।
अन्य सभी उत्तर बहुत अच्छे हैं। लेकिन इस बारे में एक महत्वपूर्ण प्रयोज्य विस्तार है कि ghc $ का व्यवहार कैसे करता है, कि ghc प्रकार चेकर उच्च श्रेणी / परिमाणित प्रकारों के साथ अस्थिरता की अनुमति देता है। यदि आप $ id
उदाहरण के प्रकार को देखते हैं तो आप पाएंगे कि यह एक ऐसा फ़ंक्शन है जिसका तर्क स्वयं एक बहुरूपिक फ़ंक्शन है। समतुल्य परेशान ऑपरेटर के साथ उस तरह की छोटी चीजें समान लचीलापन नहीं दी जाती हैं। (यह वास्तव में मुझे आश्चर्यचकित करता है कि क्या $ एक ही उपचार के योग्य है या नहीं)