हास्केल में डॉट ऑपरेटर: अधिक स्पष्टीकरण की आवश्यकता है


86

मैं समझने की कोशिश कर रहा हूँ कि इस हास्केल कोड में डॉट ऑपरेटर क्या कर रहा है:

sumEuler = sum . (map euler) . mkList

संपूर्ण स्रोत कोड नीचे है।

मेरी समझ

डॉट ऑपरेटर दो कार्यों sumऔर इनपुट map eulerके परिणाम के mkListरूप में परिणाम ले रहा है ।

लेकिन, sumयह एक फ़ंक्शन नहीं है यह फ़ंक्शन का तर्क है, है ना? तो यहां पर क्या हो रहा है?

इसके अलावा, क्या (map euler)कर रहा है?

कोड

mkList :: Int -> [Int]
mkList n = [1..n-1]

euler :: Int -> Int
euler n = length (filter (relprime n) (mkList n))

sumEuler :: Int -> Int
sumEuler = sum . (map euler) . mkList

जवाबों:


138

सीधे शब्दों में कहें, .फ़ंक्शन रचना है, जैसे गणित में:

f (g x) = (f . g) x

आपके मामले में, आप एक नया फ़ंक्शन बना रहे हैं, sumEulerजिसे इस तरह भी परिभाषित किया जा सकता है:

sumEuler x = sum (map euler (mkList x))

आपके उदाहरण में शैली को "बिंदु-मुक्त" शैली कहा जाता है - फ़ंक्शन के तर्क को छोड़ दिया जाता है। यह कई मामलों में स्पष्ट कोड के लिए बनाता है। (पहली बार इसे देखने के लिए आपको कड़ी मेहनत करनी पड़ सकती है, लेकिन थोड़ी देर बाद आपको इसकी आदत हो जाएगी। यह एक आम हास्केल मुहावरा है।)

यदि आप अभी भी भ्रमित हैं, तो यह .यूनिक्स पाइप जैसी किसी चीज से संबंधित होने में मदद कर सकता है । यदि इसका आउटपुट इनपुट fबन जाता है g, जिसका आउटपुट इनपुट बन जाता है h, तो आप इसे कमांड-लाइन पर लिखेंगे f < x | g | h। हास्केल में, .यूनिक्स की तरह काम करता है |, लेकिन "बैकवर्ड" - h . g . f $ x। जब सूची कहती है, तो मुझे यह सूचना काफी मददगार लगती है। जैसे कुछ अनजाने निर्माण के बजाय map (\x -> x * 2 + 10) [1..10], आप बस लिख सकते हैं (+10) . (*2) <$> [1..10]। (और, यदि आप केवल उस फ़ंक्शन को एक मान पर लागू करना चाहते हैं, तो यह (+10) . (*2) $ 10सुसंगत है!)

हास्केल विकी का कुछ और विवरण के साथ एक अच्छा लेख है: http://www.haskell.org/haskellwiki/Pointfree


1
टिनी क्विबल: पहला कोड स्निपेट वास्तव में मान्य हास्केल नहीं है।
स्विफ्टनामेस

2
@SwiftsNamesake उन लोगों के लिए जो हास्केल में धाराप्रवाह नहीं हैं, क्या आपका मतलब सिर्फ यह है कि एकल बराबरी का संकेत यहाँ सार्थक नहीं है? (तो स्निपेट को " f (g x)= (f . g) x" प्रारूपित किया जाना चाहिए था ?) या कुछ और?
user234461

1
@ user234461 बिल्कुल, हाँ। ==यदि आपको मान्य मानक हास्केल चाहिए था तो आपको इसके बजाय आवश्यकता होगी ।
स्विफ्टनामेक

यह थोड़ा स्निपेट ऊपर सिर्फ सोना है। अन्य उत्तरों की तरह यहाँ भी सही हैं लेकिन उस स्निपेट ने सीधे मेरे सिर में सहजता से क्लिक किया जिससे आपका बाकी उत्तर पढ़ना अनावश्यक हो गया।
तरिक वेलिंग

24

द। ऑपरेटर कार्यों की रचना करता है। उदाहरण के लिए,

a . b

जहाँ a और b फ़ंक्शन हैं, एक नया फ़ंक्शन है जो अपने तर्कों पर b चलाता है, फिर उन परिणामों पर। तुम्हारा कोड

sumEuler = sum . (map euler) . mkList

बिल्कुल वैसा ही है:

sumEuler myArgument = sum (map euler (mkList myArgument))

लेकिन उम्मीद है कि पढ़ने में आसान होगा। मानचित्र यूलर के आसपास के कारण हैं , क्योंकि यह स्पष्ट करता है कि 3 कार्यों की रचना की जा रही है: योग , मानचित्र यूलर और mkList - मानचित्र यूलर एक एकल फ़ंक्शन है।


23

sumहास्केल प्रस्तावना में एक कार्य है, एक तर्क नहीं है sumEuler। इसका प्रकार है

Num a => [a] -> a

फ़ंक्शन कंपोजिशन ऑपरेटर . में टाइप होता है

(b -> c) -> (a -> b) -> a -> c

तो हमारे पास

           euler           ::  Int -> Int
       map                 :: (a   -> b  ) -> [a  ] -> [b  ]
      (map euler)          ::                 [Int] -> [Int]
                    mkList ::          Int -> [Int]
      (map euler) . mkList ::          Int ->          [Int]
sum                        :: Num a =>                 [a  ] -> a
sum . (map euler) . mkList ::          Int ->                   Int

ध्यान दें कि Intवास्तव में Numटाइपकास्ट का एक उदाहरण है ।


11

द। ऑपरेटर का उपयोग फ़ंक्शन संरचना के लिए किया जाता है। गणित की तरह ही, यदि आपको f (x) और g (x) के कार्य करने हैं। g f (g (x)) हो जाता है।

मानचित्र एक अंतर्निहित फ़ंक्शन है जो किसी फ़ंक्शन को किसी सूची में लागू करता है। फ़ंक्शन को कोष्ठक में रखकर फ़ंक्शन को एक तर्क के रूप में माना जाता है। इसके लिए एक शब्द है करी । आपको यह देखना चाहिए।

क्या है कि यह दो तर्कों के साथ एक फ़ंक्शन लेता है, यह तर्क योजक लागू करता है। (नक्शा यूलर) सही है? और परिणाम एक नया कार्य है, जो केवल एक तर्क लेता है।

योग। (मानचित्र यूलर)। mkList मूल रूप से सभी को एक साथ रखने का एक फैंसी तरीका है। मुझे कहना होगा, मेरा हास्केल थोड़ा कठोर है, लेकिन हो सकता है कि आप उस आखिरी समारोह को एक साथ रख सकें?


5

हास्केल में डॉट ऑपरेटर

मैं समझने की कोशिश कर रहा हूँ कि इस हास्केल कोड में डॉट ऑपरेटर क्या कर रहा है:

sumEuler = sum . (map euler) . mkList

संक्षिप्त जवाब

बिना डॉट्स के समतुल्य कोड, बस

sumEuler = \x -> sum ((map euler) (mkList x))

या लंबोदर के बिना

sumEuler x = sum ((map euler) (mkList x))

क्योंकि डॉट (।) फ़ंक्शन संरचना को इंगित करता है।

लंबा जवाब

पहले, के आंशिक आवेदन को सरल बनाने के eulerलिए map:

map_euler = map euler
sumEuler = sum . map_euler . mkList

अब हमारे पास बस डॉट्स हैं। इन बिंदुओं से क्या संकेत मिलता है?

से स्रोत :

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

इस प्रकार (.)है तो लिखें ऑपरेटर

लिखें

गणित में, हम कार्यों की संरचना, f (x) और g (x) लिख सकते हैं, अर्थात, f (g (x)),

(च) जी) (एक्स)

जिसे "g के साथ रचित f" पढ़ा जा सकता है।

तो हास्केल में, एफ, जी, या एफ जी के साथ रचित, लिखा जा सकता है:

f . g

रचना साहचर्य है, जिसका अर्थ है कि रचना ऑपरेटर के साथ लिखा हुआ f (g (h (x))), किसी भी अस्पष्टता के बिना कोष्ठक को छोड़ सकता है।

यही है, क्योंकि (f) g) equivalent h f g (g) h) के बराबर है, हम बस f write g। H लिख सकते हैं।

पीछे घूमना

हमारे पहले के सरलीकरण पर वापस आते हुए, यह:

sumEuler = sum . map_euler . mkList

बस इसका मतलब है कि sumEulerउन कार्यों की एक अज्ञात संरचना है:

sumEuler = \x -> sum (map_euler (mkList x))

4

डॉट ऑपरेटर बाईं ओर फ़ंक्शन को लागू करता है ( sum) दाईं ओर फ़ंक्शन के आउटपुट पर। आपके मामले में, आप कई कार्य एक साथ चेनिंग रहे हैं - आप का परिणाम गुजर रहे हैं mkListकरने के लिए (map euler), और उसके बाद करने के लिए इस बात का परिणाम गुजर sumइस साइट का कई अवधारणाओं से अच्छा परिचय है।

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