2012-06-09 13 views
10

(+) और (++) केवल mappend की विशेषज्ञता हैं; क्या मैं सही हू? उन्हें क्यों चाहिए? यह बेकार नकल है क्योंकि हास्केल में इन शक्तिशाली टाइपक्लास और टाइप अनुमान हैं। मान लें कि हम (+) और (++) हटाते हैं और दृश्य सुविधा और टाइपिंग लाभ के लिए mappend(+) का नाम बदलें। कोडिंग शुरुआती के लिए अधिक सहज ज्ञान युक्त छोटे और अधिक समझ में आता होगा:हास्केल: डुप्लिकेट फ़ंक्शन (+) और (++), मैपेंड

--old and new 
1 + 2 
--result 
3 

--old 
"Hello" ++ " " ++ "World" 
--new 
"Hello" + " " + "World" 
--result 
"Hello World" 

--old 
Just [1, 2, 3] `mappend` Just [4..6] 
--new 
Just [1, 2, 3] + Just [4..6] 
--result 
Just [1, 2, 3, 4, 5, 6] 

(यह मेरे सपने में आता है।)। तीन, और शायद अधिक, एक ही चीज़ के लिए कार्य एक सुंदर भाषा के लिए एक अच्छी बात नहीं है जो हास्केल जैसे अवशोषण और सामान पर जोर देती है। fmap एक ही है, या लगभग, के रूप में map, (.), liftM, mapM, forM, ... मुझे पता है कि fmap के लिए historial कारण हैं, लेकिन क्या monoids के बारे में: मैं भी monads साथ repetitions के एक ही तरह देखा था? क्या हास्केल इस बारे में कुछ योजना बना रहा है? यह कुछ कोड तोड़ देगा, लेकिन मैंने सुना है, हालांकि मुझे यकीन नहीं है, एक आने वाला संस्करण है जिसमें बहुत अच्छे बदलाव होंगे, जो एक अच्छा अवसर है। यह बहुत दयालु है ... कम से कम, एक कांटा सस्ती है?

संपादित जवाब मैंने पढ़ा है, वहाँ तथ्य यह है कि संख्या के लिए, या तो (*) या (+)mappend में फिट सकता है। वास्तव में, मुझे लगता है कि (*)Monoid का हिस्सा होना चाहिए! देखो:

वर्तमान में, mempty और mconcat कार्यों के बारे में भूलना, हमारे पास केवल mappend है।

class Monoid m where 
    mappend :: m -> m -> m 

लेकिन हम ऐसा कर सकते हैं:

class Monoid m where 
    mappend :: m -> m -> m 
    mmultiply :: m -> m -> m 

यह (शायद, मैं नहीं है, हालांकि काफी इसके बारे में अभी तक) होगा इस प्रकार व्यवहार करते हैं:

3 * 3 
mempty + 3 + 3 + 3 
0 + 3 + 3 + 3 
9 

Just 3 * Just 4 
Just (3 * 4) 
Just (3 + 3 + 3 +3) 
Just 12 

[1, 2, 3] * [10, 20, 30] 
[1 * 10, 2 * 10, 3 * 10, ...] 
[10, 20, 30, 20, 40, 60, ...] 

असल में 'mmultiply' केवल 'mappend' के संदर्भ में परिभाषित किया जाएगा ताकि Monoid के उदाहरणों के लिए इसे फिर से परिभाषित करने की आवश्यकता न हो! फिर Monoid गणित के करीब है; शायद हम कक्षा में (-) और (/) जोड़ सकते हैं! यदि यह काम करता है, तो मुझे लगता है कि यह Sum और Product के साथ-साथ फ़ंक्शंस डुप्लिकेशंस के मामले को हल करेगा: mappend(+) और नया mmultiply केवल (*) है। असल में मैं "पुल अप" के साथ कोड का एक रिफैक्टरिंग का सुझाव देता हूं। ओह, हमें (*) के लिए एक नया mempty भी चाहिए। हम सार एक वर्ग MonoidOperator में इन ऑपरेटरों सकता है और इस प्रकार Monoid को परिभाषित:

class (Monoid m) => MonoidOperator mo m where 
    mempty :: m 
    mappend :: m -> m -> m 

instance MonoidOperator (+) m where 
    mempty = 0 
    mappend = --definition of (+) 

instance MonoidOperator (*) where 
    --... 

class Monoid m where 
    -... 

खैर मैं कैसे अभी तक यह करने के लिए पता नहीं है, लेकिन मुझे लगता है कि यह सभी के लिए एक शांत समाधान है।

+0

सैद्धांतिक रूप से, '+' और '*' 'मैपेंड 'की विशेषज्ञता हैं लेकिन व्यावहारिक रूप से वे नहीं हैं: यह विचार [न्यूम' के आसपास [पतली रैपर] के रूप में लागू किया गया है (http://www.haskell.org /ghc/docs/latest/html/libraries/base/Data-Monoid.html#g:3)। (और इसे किसी अन्य तरीके से समझदारी से लागू नहीं किया जा सकता है, एक के लिए, '+' और '*' दोनों मोनोइड ऑपरेशन के रूप में मान्य हैं और इसका उपयोग करने के लिए कोई विशिष्ट तरीका नहीं होगा।) – huon

+2

संख्याएं 'मोनॉयड' 'उदाहरण दो अलग-अलग तरीकों से - योग और उत्पाद। वास्तव में डुप्लिकेट फ़ंक्शंस हैं, जिन्हें एक साथ विलय किया जाना चाहिए ('map',' fmap', 'liftM',' liftA'; '(<*>)' 'ap' और कई अन्य), लेकिन मुझे नहीं लगता कि 'mappend' (या '(<>)' नए संस्करणों में) उन कार्यों में से एक है जिन्हें मर्ज की आवश्यकता है। – Vitus

+0

आप पहली पोस्ट के संपादन के बारे में क्या सोचते हैं? – L01man

उत्तर

10

आप यहां कुछ अलग अवधारणाओं को मिश्रण करने की कोशिश कर रहे हैं।

अंकगणित और सूची concatenation बहुत व्यावहारिक, प्रत्यक्ष संचालन हैं। यदि आप लिखते हैं:

[1, 2] ++ [3, 4] 

... आप जानते हैं कि आपको परिणामस्वरूप [1, 2, 3, 4] मिल जाएगा।


एक Monoid एक गणितीय बीजीय अवधारणा एक अधिक अमूर्त स्तर पर है। इसका मतलब है कि mappend का शाब्दिक अर्थ यह नहीं है कि "इसे इसमें शामिल करें;" इसका कई अन्य अर्थ हो सकते हैं। जब आप लिखें:

[1, 2, 3, 4] -- concatenation, mempty is [] 

[4, 6]  -- vector addition with truncation, mempty is [0,0..] 

[3, 6, 4, 8] -- some inner product, mempty is [1] 

[3, 4, 6, 8] -- the cartesian product, mempty is [1] 

[3, 4, 1, 2] -- flipped concatenation, mempty is [] 

[]   -- treating lists like `Maybe a`, and letting lists that 
      -- begin with positive numbers be `Just`s and other lists 
      -- be `Nothing`s, mempty is [] 

क्यों सूचियों के लिए mappend सिर्फ सूचियों को श्रेणीबद्ध करता है:

[1, 2] `mappend` [3, 4] 

... इन कुछ वैध परिणाम है कि कि आपरेशन का उत्पादन हो सकता है कर रहे हैं? क्योंकि यह केवल मोनोइड्स की परिभाषा है कि जिन लोगों ने हास्केल रिपोर्ट लिखी है, वे डिफ़ॉल्ट कार्यान्वयन के रूप में चुने गए हैं, शायद इसलिए कि यह किसी भी सूची के सभी तत्व प्रकारों के लिए समझ में आता है। और वास्तव में, आप विभिन्न नए प्रकारों में उन्हें लपेटकर सूचियों के लिए एक वैकल्पिक मोनॉयड उदाहरण का उपयोग कर सकते हैं; उदाहरण के लिए सूचियों के लिए एक वैकल्पिक मोनोइड उदाहरण है जो उन पर कार्टशियन उत्पाद करता है।

"मोनॉयड" की अवधारणा का एक निश्चित अर्थ है और गणित में एक लंबा इतिहास है, और हास्केल में इसकी परिभाषा को बदलना मतलब गणितीय अवधारणा से अलग हो जाना चाहिए, जो नहीं होना चाहिए। एक मोनॉयड बस एक खाली तत्व का विवरण नहीं है और एक (शाब्दिक) संलग्न/संयोग ऑपरेशन; यह अवधारणाओं की एक विस्तृत श्रृंखला के लिए आधार है जो मोनॉयड प्रदान करता है कि इंटरफ़ेस का पालन करता है।


अवधारणा है कि आप देख रहे हैं संख्या के लिए विशिष्ट है, एक अवधारणा पहले से मौजूद है और Semiring कहा जाता है कि (यदि आप mmultiply या उदाहरण के लिए Maybe a के सभी उदाहरणों के लिए हो सकता है mproduce/mproduct की तरह कुछ को परिभाषित नहीं कर सका क्योंकि) गणित में (ठीक है, आपने वास्तव में अपने प्रश्न में सहयोगीता को कवर नहीं किया है, लेकिन आप अपने उदाहरणों में अलग-अलग अवधारणाओं के बीच कूद रहे हैं, कभी-कभी कभी-कभी सहयोगीता का पालन करते हैं, कभी-कभी नहीं, लेकिन सामान्य विचार समान है)।

हास्केल में सेमिरिंग के पहले से ही कार्यान्वयन हैं, उदाहरण के लिए algebra पैकेज में।

हालांकि, एक मोनोइड आम तौर पर एक सेमिंग नहीं होता है, और विशेष रूप से अतिरिक्त और गुणा के अलावा वास्तविक संख्याओं के लिए सेमिरींग के कई कार्यान्वयन भी होते हैं।मोनोइड जैसे बहुत अच्छी तरह से परिभाषित प्रकार के वर्गों में व्यापक सामान्यीकृत जोड़ों को जोड़ना सिर्फ इसलिए नहीं किया जाना चाहिए क्योंकि यह "साफ होगा" या "कुछ कीस्ट्रोक बचाएगा;" एक कारण है कि हमारे पास (++), (+) और mappend अलग-अलग अवधारणाओं के रूप में हैं, क्योंकि वे पूरी तरह से अलग कम्प्यूटेशनल विचारों का प्रतिनिधित्व करते हैं।

+0

धन्यवाद, मुझे अब सब कुछ बेहतर समझ है। मुझे लगता है कि मैं थोड़ा और गणित सीखने के बाद वापस आऊंगा:}। – L01man

+0

यह वास्तव में दुर्भाग्यपूर्ण है कि 'न्यू' में सभी ऑपरेशन एक ही टाइपक्लास में हैं। एक बात के लिए इसका मतलब है कि परिचालन जिन्हें 'कॉम्प्लेक्स इंटेगर' के लिए अच्छी तरह से परिभाषित किया जाना चाहिए, का उपयोग नहीं किया जा सकता है! –

+0

@deflemstr अपना उत्तर पढ़ने के बाद मेरे पास यह धारणा है कि आप इस सवाल को हवा में छोड़ देते हैं कि "सूची 'उदाहरण' सूची 'के लिए कितना अलग है। मेरा मतलब है, आपने कहा था कि 'सूची'' के लिए कई संभावित' मैपेंड'' हैं, जो '' '' के लिए लागू होते हैं, हालांकि '' सूची 'के लिए डिफ़ॉल्ट रूप से चयन किया गया था, जबकि डिफ़ॉल्ट रूप से' 'Num''। तो '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' आप अभी भी एक नए प्रकार के साथ गुणा कर सकते हैं। – Gustavo

3

वैसे संख्याओं के लिए दो मोनोइड्स हैं - Product और Sum, आप इससे कैसे निपटेंगे?

तीन, और शायद अधिक, एक ही चीज़ के लिए कार्य एक सुंदर भाषा के लिए अच्छी बात नहीं है जो हास्केल जैसे अवशोषण और सामान पर जोर देती है।

एब्स्ट्रैक्शन कोड डुप्लिकेशन को समाप्त करने के बारे में नहीं हैं। अंकगणित और मोनोइड ऑपरेशंस दो अलग-अलग विचार हैं, और ऐसे मामलों के बावजूद जहां वे समान अर्थशास्त्र साझा करते हैं, आप उन्हें विलय करके कुछ हासिल नहीं करते हैं।

+0

मैंने इसे हल करने के लिए एक तरीका सुझाए जाने के लिए प्रश्न संपादित किया। – L01man

+3

... और 'उत्पाद' और' Sum' संख्याओं पर केवल दो संभावित मोनोइड्स नहीं हैं, या तो। वे सिर्फ दो सबसे अधिक इस्तेमाल किए जाने वाले मोनोइड्स होते हैं। –

+0

मैंने अभी देखा है कि न्यूम मोनॉयड का उदाहरण नहीं है। मुझे "संचालन" के लिए मोनोइड्स रखना अजीब लगता है, न कि संख्याओं के लिए। – L01man

8

(+)/(*)

जबकि (+) और (*) को mappend का नाम बदलने पर दोनों monoids वे अतिरिक्त distributivity कानून हैं, दो आपरेशन से संबंधित है, साथ ही cancellative कानूनों जैसे हैं 0 * x = 0. अनिवार्य रूप से, (+) और (*)ring बनाते हैं। किसी अन्य प्रकार के दो मोनोइड्स इन अंगूठी (या यहां तक ​​कि कमजोर अर्ध-अंगूठी) गुणों को पूरा नहीं कर सकते हैं। ऑपरेटर (+) और (*) का नामकरण उनके अतिरिक्त (अंतर-संबंधित) गुणों का सूचक है। इस प्रकार, मैं mappend को + या * नाम देकर पारंपरिक गणितीय अंतर्ज्ञान को कम करने से बचूंगा क्योंकि ये नाम अतिरिक्त गुणों का सुझाव देते हैं जो होल्ड नहीं हो सकते हैं। कभी-कभी बहुत अधिक अधिभार (यानी बहुत अधिक सामान्यीकरण) अंतर्ज्ञान की हानि और इस प्रकार उपयोगिता का नुकसान होता है।

आप तो आप Num इन से की आवृत्ति प्राप्त करने के लिए पसंद कर सकते हैं दो monoids जो अंगूठी के कुछ प्रकार के रूप में है के लिए हो रहा है, तो नाम "+" और "*" के रूप में अतिरिक्त गुणों सुझाव देते हैं।

conflating (++) और mappend

mappend(++) को नाम बदल रहा है और अधिक उपयुक्त हो सकता है के रूप में वहाँ (++) के साथ कम अतिरिक्त मानसिक सामान है पर। दरअसल, चूंकि सूचियां मुक्त मोनोइड (यानी, कोई अतिरिक्त गुण वाले मोनोइड नहीं हैं) तो पारंपरिक सूची-कॉन्सटेन्टेशन ऑपरेटर (++) का उपयोग करके एक मोनोइड के बाइनरी ऑपरेशन को इंगित करने के लिए एक भयानक विचार नहीं लगता है।

एक प्रकार

के लिए कई monoids को परिभाषित करने पर आप का कहना है के रूप में, दोनों (+) हैं (*) monoids हैं, लेकिन दोनों Monoid का एक उदाहरण एक ही प्रकार t के लिए नहीं किया जा सकता। एक समाधान, जिसे आप अर्ध-प्रदान करते हैं, दो मोनोइड्स को अलग करने के लिए Monoid कक्षा में एक अतिरिक्त प्रकार पैरामीटर होना है। ध्यान दें कि वर्गों को टाइप केवल प्रकार के द्वारा पैरामीटर किया जा सकता है, अभिव्यक्ति द्वारा नहीं, जैसा कि आप अपने प्रश्न में दिखाते हैं। एक उपयुक्त परिभाषा होगा कुछ की तरह:

class Monoid m variant where 
mappend :: variant -> m -> m -> m 
mempty :: variant -> m 

data Plus = Plus 
data Times = Times 

instance Monoid Int Plus where 
    mappend Plus x y = x `intPlus` y 
    mempty = 0 

instance Monoid Int Times where 
    mappend Times x y = x `intTimes` y 
    mempty = 1 

(+) = mappend Plus 
(*) = mappend Times 

की mappend/mempty एक विशेष ऑपरेशन के लिए हल किया जाना अनुप्रयोगों के लिए आदेश में, प्रत्येक प्रकार है कि विशेष रूप monoid "संस्करण" इंगित करता है साक्षी एक मूल्य रखना चाहिए।

इसके अलावा: आपके प्रश्न का शीर्षक mconcat का उल्लेख करता है।mconcatविपक्ष mappend साथ और mempty साथ शून्य की जगह कुछ अन्य monoid अर्थात करने के लिए स्वतंत्र monoid से monoid समरूपता है - यह करने के लिए mappend एक बिल्कुल अलग ऑपरेशन है।

+0

धन्यवाद यह बहुत स्पष्ट है। मैंने शीर्षक बदल दिया। – L01man

संबंधित मुद्दे