सवाल '<<' ऑपरेटर का अर्थ एल्म में क्या है?


निम्नलिखित कोड में से लिया गया एल्म फॉर्म उदाहरण, लाइन 122, क्या करता है << ऑपरेटर का मतलब है?

Field.field Field.defaultStyle (Signal.send updateChan << toUpdate) "" content

इसे नहीं मिला एल्म वाक्यविन्यास संदर्भ

इसका मतलब यह है कि जब क्षेत्र बदलता है, तो उसे भेजने की बजाय content सेवा मेरे updateChanभेजो toUpdate सेवा मेरे updateChan?


44
2017-12-12 10:29


मूल


यदि आप हास्केल से आ रहे हैं: << का एनालॉग है . हास्केल में - ZhekaKozlov


जवाब:


<< कोर लाइब्रेरी में परिभाषित एक फ़ंक्शन रचना ऑपरेटर है Basics। मूल बातें से सभी कार्यों को एएमएम परियोजनाओं में अयोग्य घोषित किया जाता है।

एल्म प्रकार प्रणाली

चलो एल्म प्रकार प्रणाली की मूल बातें याद करते हैं।

एल्म है स्थिर रूप से टाइप किया गया। इसका मतलब है कि एएलएम में प्रत्येक चर या फ़ंक्शन में एक प्रकार होता है, और यह प्रकार कभी भी नहीं बदलता है। एल्म में प्रकार के उदाहरण हैं:

  • Int
  • String
  • Maybe Bool
  • { name : String, age : Int }
  • Int -> Int
  • Int -> String -> Maybe Char

स्टेटिक टाइपिंग का अर्थ है कि कंपाइलर सभी कार्यों के प्रकार सुनिश्चित करता है और चर संकलन के दौरान सही हैं, इसलिए आपके पास रनटाइम प्रकार की त्रुटियां नहीं हैं। दूसरे शब्दों में, आपके पास कभी भी प्रकार का कार्य नहीं होगा String -> String प्राप्त करना या लौटना Int, कोड जो यह अनुमति भी संकलित नहीं करेगा।

आप कंक्रीट प्रकार को बदलकर अपने कार्यों को पॉलिमॉर्फिक भी बना सकते हैं String या Maybe Int एक प्रकार परिवर्तनीय के साथ, जो एक मनमाना लोअरकेस स्ट्रिंग है, जैसे कि a। कई एल्म कोर फ़ंक्शन टाइप पॉलीमोर्फिक हैं, उदाहरण के लिए List.isEmpty प्रकार है List a -> Bool। यह एक लेता है List कुछ प्रकार का और प्रकार का मूल्य देता है Bool

यदि आप एक ही प्रकार परिवर्तनीय फिर से देखते हैं, तो इस प्रकार चर के उदाहरण एक ही प्रकार के होना चाहिए। उदाहरण के लिए List.reverse प्रकार है List a -> List a। तो अगर आप आवेदन करते हैं List.reverse पूर्णांक की एक सूची (यानी कुछ प्रकार के लिए List Int), यह मर्जी पूर्णांक की एक सूची वापस लौटें। ऐसा कोई तरीका नहीं है कि फ़ंक्शन पूर्णांक की एक सूची ले सकता है, लेकिन तारों की एक सूची वापस कर सकता है। यह संकलक द्वारा गारंटीकृत है।

एल्म में सभी कार्य हैं curried डिफ़ॉल्ट रूप से। इसका अर्थ यह है कि यदि आपके पास 2 तर्कों का कार्य है, तो इसे 1 तर्क के फ़ंक्शन में बदल दिया गया है जो 1 तर्क का कार्य देता है। यही कारण है कि आप एल्म के अनुप्रयोग सिंटैक्स को जावा, सी ++, सी #, पायथन इत्यादि जैसी अन्य भाषाओं में फ़ंक्शन एप्लिकेशन से बहुत अलग हैं। लिखने का कोई कारण नहीं है someFunction(arg1, arg2), जब आप लिख सकते हैं someFunction arg1 arg2। क्यूं कर? क्योंकि वास्तव में someFunction arg1 arg2 वास्तव में है ((someFunction arg1) arg2)

करी बनाना बनाता है आंशिक आवेदन मुमकिन। मान लीजिए कि आप आंशिक रूप से आवेदन करना चाहते हैं List.memberList.member एक प्रकार है a -> List a -> Bool। हम इस प्रकार को "List.member प्रकार के 2 तर्क लेता है a और टाइप करें List a"। लेकिन हम इस प्रकार को "List.member प्रकार के 1 तर्क लेता है a। यह प्रकार का एक कार्य देता है List a -> Bool"। इसलिए हम एक समारोह बना सकते हैं isOneMemberOf = List.member 1, जिसमें प्रकार होगा List Int -> Bool

इस का मतलब है कि -> कार्यों के एनोटेशन प्रकार में सही-सहयोगी है। दूसरे शब्दों में, a -> List a -> Bool के समान है a -> (List a -> Bool)

इन्फिक्स और उपसर्ग नोटेशन

कोई इंफिक्स ऑपरेटर वास्तव में पर्दे के पीछे एक साधारण काम है। यह तब होता है जब फ़ंक्शन नाम में केवल गैर-अल्फान्यूमेरिक प्रतीकों (जैसे $, <|, <<, आदि) होते हैं, इसे 2 तर्कों के बीच रखा जाता है, न कि उनके सामने (सामान्य कार्यों की तरह)।

लेकिन आप अभी भी एक बाइनरी ऑपरेटर डाल सकते हैं + 2 तर्कों के सामने, इसे कोष्ठक में संलग्न करके, इसलिए नीचे दिए गए 2 फ़ंक्शन एप्लिकेशन समकक्ष हैं:

2 + 3 -- returns 5
(+) 2 3 -- returns 5, just like the previous one

इंफिक्स ऑपरेटर केवल सामान्य कार्य हैं। उनके बारे में कुछ खास नहीं है। आप किसी भी अन्य फ़ंक्शन की तरह आंशिक रूप से उन्हें लागू कर सकते हैं:

addTwo : Int -> Int
addTwo = (+) 2

addTwo 3 -- returns 5

फंक्शन संरचना

(<<) कोर लाइब्रेरी में परिभाषित एक फ़ंक्शन रचना ऑपरेटर है Basics। मूलभूत बातों के सभी कार्यों को एल्म परियोजनाओं में अयोग्य घोषित किया जाता है, जिसका अर्थ है कि आपको लिखना नहीं है import Basics exposing (..), यह डिफ़ॉल्ट रूप से पहले ही किया जा चुका है।

तो बस किसी अन्य ऑपरेटर की तरह, (<<) बस एक समारोह है, किसी अन्य की तरह। इसका प्रकार क्या है?

(<<) : (b -> c) -> (a -> b) -> a -> c

इसलिये -> सही सहयोगी है, यह बराबर है:

(<<) : (b -> c) -> (a -> b) -> (a -> c)

दूसरे शब्दों में, (<<) प्रकार के 2 कार्यों लेता है b -> c तथा a -> b क्रमशः, और प्रकार के एक समारोह देता है a -> c। यह 2 कार्यों को एक में बना देता है। वह कैसे काम करता है? आइए सरलता के लिए एक संक्षिप्त उदाहरण देखें। मान लें कि हमारे पास 2 सरल कार्य हैं:

addOne = (+) 1
multTwo = (*) 2

मान लीजिए कि हमारे पास नहीं है (+), केवल addOne, हम एक फ़ंक्शन कैसे बनाएंगे जो 3 जोड़ता है, न कि 1? बहुत सरल, हम लिखेंगे addOne एक साथ 3 बार:

addThree : Int -> Int
addThree = addOne << addOne << addOne

क्या होगा यदि हम एक ऐसा फ़ंक्शन बनाना चाहते हैं जो 2 जोड़ता है, तो 4 से गुणक?

ourFunction : Int -> Int
ourFunction = multTwo << multTwo << addOne << addOne

(<<) दाएं से बाएं कार्यों को रचना करता है। लेकिन उपर्युक्त उदाहरण सरल है, क्योंकि सभी प्रकार समान हैं। हम सूची के सभी क्यूब्स का योग कैसे प्राप्त करेंगे?

isEven : Int -> Bool
isEven n = n % 2 == 0

cube : Int -> Int
cube n = n * n * n

ourFunction2 : List Int -> Int
ourFunction2 = List.sum << filter isEven << map cube

(>>) वही कार्य है, लेकिन तर्कों के साथ फ़्लिप किया गया है, इसलिए हम उसी संरचना को बाएं से दाएं से लिख सकते हैं:

ourFunction2 = map cube >> filter isEven >> List.sum

संक्षिप्त

जब आप कुछ ऐसा देखते हैं h << g << f, तो आप उसे जानते हैं f, g, h कार्य हैं जब यह निर्माण होता है h << g << f एक मूल्य पर लागू होता है x, तो आप जानते हैं:

  • एल्म पहले लागू होता है f सेवा मेरे x
  • फिर लागू होता है g पिछले चरण के परिणामस्वरूप
  • फिर लागू होता है h पिछले चरण के परिणामस्वरूप

इसलिये (negate << (*) 10 << sqrt) 25 के बराबर होती है -50.0, क्योंकि आप पहले 25 के वर्ग रूट लेते हैं और 5 प्राप्त करते हैं, तो आप 5 से 10 गुणा करते हैं और 50 प्राप्त करते हैं, फिर आप 50 को अस्वीकार करते हैं और -50 प्राप्त करते हैं।

क्यों << और नहीं।

एल्म 0.13 से पहले (देखें घोषणा) समारोह संरचना ऑपरेटर था (.), और इसका व्यवहार वर्तमान के समान था (<<)(<<) एफ # भाषा से एल्म 0.13 में अपनाया गया था (देखें गिथूब मुद्दा)। एल्म 0.13 भी जोड़ा गया (>>) के बराबर के रूप में flip (<<), तथा (<|) फ़ंक्शन एप्लिकेशन ऑपरेटर के प्रतिस्थापन के रूप में ($), तथा (|>) के बराबर के रूप में flip (<|)

इंफिक्स फ़ंक्शन कॉल

आप सोच रहे होंगे कि क्या आप एक साधारण अल्फान्यूमेरिक फ़ंक्शन नाम को इंफिक्स बाइनरी ऑपरेटर में बदल सकते हैं। एल्म 0.18 से पहले आप फ़ंक्शन इंफिक्स बनाने के लिए बैकटिक्स का उपयोग करेंगे, इसलिए 2 से नीचे समकक्ष होगा:

max 1 2 -- returns 2
1 `max` 2 -- returns 2

एल्म 0.18 इस सुविधा को हटा दिया। आप इसे एल्म में और नहीं कर सकते हैं, लेकिन भाषाओं की तरह हास्केल तथा PureScript अभी भी इसे लें।


96
2017-08-18 16:50



काश यह आदमी मेरा शिक्षक था। इसे आधिकारिक दस्तावेज में होना जरूरी है जिसे मुझे कार्यात्मक एमएल आधारित भाषाओं में शुरुआती लोगों के लिए कुछ महत्वपूर्ण जानकारी की कमी होनी चाहिए। - frostymarvelous


<< एक समारोह संरचना है - रिटर्न समारोह।

संरचना कम्प्यूटेशंस, कार्यों की श्रृंखला का एक पाइप बनाता है। यह पाइप इनपुट के लिए इंतजार कर रही है, और जब प्रदान की जाती है, तो पहला फ़ंक्शन गणना शुरू करता है, अगले आउटपुट को आउटपुट भेजता है।

import Html

add x y =
    Debug.log "x" x + Debug.log "y" y

add9 =
    add 4 << add 5

main =
    Html.text <| toString <| add9 2

ध्यान दें: उपर्युक्त उदाहरण में मैं उपयोग करता हूं आंशिक आवेदन। इसका मतलब है कि मैं कार्य करने के लिए सभी पैरामीटर प्रदान नहीं करता हूं और नतीजतन मुझे कार्य मिलता है।

यदि आप वेब ब्राउज़र में उदाहरण से ऊपर चलाते हैं और कंसोल आउटपुट देखते हैं, तो आप देखेंगे:

x: 5
y: 2
x: 4
y: 7

अगर हम इसे गणित परिचालन के रूप में लिखते हैं तो यह इस तरह दिखेगा:

4 + (5 + 2)
4 + 7

ध्यान दें: हम आगे के संस्करण का भी उपयोग कर सकते हैं >>

हस्ताक्षर पढ़ना

इस ऑपरेटर के हस्ताक्षर को देखते हुए:

(<<) : (b -> c) -> (a -> b) -> a -> c

के लिये << ऑपरेटर, एक समारोह है b -> c पहले पैरामीटर के रूप में, और एक समारोह के रूप में a -> b दूसरे के रूप में:

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

लेकिन एक तीसरा पैरामीटर भी है a। इसलिये -> तब सही-सहयोगी है

(<<) : (b -> c) -> (a -> b) -> a -> c

के बराबर है:

(<<) : (b -> c) -> (a -> b) -> (a -> c)

इसलिए कि << रिटर्न समारोह a -> c

संबद्धता

प्रोग्रामिंग भाषाओं में, ऑपरेटर की सहयोगीता (या स्थिरता) एक ऐसी संपत्ति है जो यह निर्धारित करती है कि समान प्राथमिकता के ऑपरेटरों को कोष्ठक की अनुपस्थिति में कैसे समूहीकृत किया जाता है; यानी प्रत्येक ऑपरेटर का मूल्यांकन किस क्रम में किया जाता है:

a = b = c के रूप में पार्स किया गया है a = (b = c)

इंफिक्स ऑपरेटर

यहां मैं उपयोग करता हूं << जैसा इंफिक्स ऑपरेटर, लेकिन हम इसे प्रीफेक्स ऑपरेटर के रूप में भी कंस्ट्रैसिस के साथ संलग्न कर सकते हैं: (<<) (b -> c) (a -> b) या (<|) (add 4) (add 5)

एल्म <0.18 अभ्यस्त आप सामान्य कार्यों को लेते हैं और उन्हें इंफिक्स ऑपरेटरों के रूप में उपयोग करते हैं।

के बारे में एक शब्द <| ऑपरेटर

<| एक फ़ंक्शन एप्लिकेशन है - रिटर्न मान

हम मूल रूप से इसेष्ठक के बजाय उपयोग करते हैं।

text (something ++ something)

के रूप में लिखा जा सकता है

text <| something ++ something

तो देख रहे हैं हस्ताक्षर इस ऑपरेटर का:

(<|) : (a -> b) -> a -> b

हम इसके लिए देख सकते हैं <| ऑपरेटर, एक समारोह है a -> b  पहले पैरामीटर, और मूल्य के रूप में a दूसरे के रूप में:

(a -> b) <| a

और यह लौटता है b

हम फ़ंक्शन एप्लिकेशन के साथ समान मूल्य प्राप्त कर सकते हैं <|:

v1 = add 4 <| add 5 <| 4
v2 = (add 4 << add 5) 4

19
2018-05-29 12:41



नाइटपिक के लिए खेद है, लेकिन इस संदर्भ में लागू "कार्यों की आलसी श्रृंखला" है? क्या एल्म का सख्ती से मूल्यांकन नहीं किया जाता है? groups.google.com/forum/#!topic/elm-discuss/9XxV9L0zoA0 - pdoherty926


यह कार्य रचना है। आपके ठोस उदाहरण के लिए इसका मतलब है

\x -> (Signal.send updateChan (toUpdate x))

एल्म में यह वाक्यविन्यास का हिस्सा नहीं है लेकिन मानक पुस्तकालय का हिस्सा है: मूल बातें। <<


11
2017-12-12 10:46



परंतु << यदि दो कार्य करता है, तो f तथा g दोनों कार्य हैं, मैं इसे देख सकता हूं f << g माध्यम \x -> f (g x)। मेरे उदाहरण में, किसके साथ toUpdate समग्र, कुछ छुपा पहचान समारोह? जबसे updateChan यदि आप लिखते हैं तो कोई फ़ंक्शन नहीं है updateChan << toUpdate, क्या इससे त्रुटि नहीं होगी? - Not an ID
मुझे यह स्निपेट आपके द्वारा प्रदान किए गए स्रोत नहीं मिल सका। से send और फील्ड हस्ताक्षर मैंने माना कि कुछ डेटा प्रकार का उपयोग किया जाता है, इसलिए updateChan एक है Channel Data तथा toUpdate फॉर्म का एक समारोह है String -> Data। देता है कि (Signal.send updateChan) प्रकार है Data -> Message तथा (Signal.send updateChan) << toUpdate प्रकार है String -> Message। - CheatEx


मेरा दूसरा प्रयास: डी

<< बनाम <|

के बीच भिन्नता << तथा <| क्या वह << कार्यों को लिखने के लिए प्रयोग किया जाता है और <| ब्रांड्स को छोड़ने के लिए प्रयोग किया जाता है।

ऐसा क्यों काम करता है

आइए टाइप एनोटेशन को देखें यहाँ:

<< : (b -> c) -> (a -> b) -> a -> c

यह परिभाषा हमें बताती है कि जब आप कार्य करने के लिए दो कार्य पास करते हैं <<, आप समारोह प्राप्त करेंगे a -> c

के साथ उदाहरण डेमो

hi a =
    a + 2
hello a =
    a * 2
bye =
    hello << hi
c =
    bye 3

c मूल्य वापसी करता है 10

पर और अधिक पढ़ें:

  • इंफिक्स ऑपरेटर - समारोह के बाईं ओर पहला तर्क,
  • आंशिक आवेदन - जब आप दो तर्कों की अपेक्षा करने के लिए एक तर्क को पास करते हैं, तो आपको एक तर्क की अपेक्षा करने वाले फ़ंक्शन मिलते हैं।

0
2017-07-29 21:05