न कि एक फ़नकार / फ़नकार / आवेदक / मोनाड के अच्छे उदाहरण?


209

किसी को यह समझाते हुए कि किस प्रकार का X वर्ग I डेटा संरचनाओं के अच्छे उदाहरणों को खोजने के लिए संघर्ष कर रहा है जो वास्तव में X हैं।

इसलिए, मैं उदाहरण के लिए अनुरोध करता हूं:

  • एक प्रकार का कंस्ट्रक्टर जो फ़नकार नहीं है।
  • एक प्रकार का कंस्ट्रक्टर जो एक फ़नकार है, लेकिन लागू नहीं है।
  • एक प्रकार का कंस्ट्रक्टर जो एक एपेक्टिव है, लेकिन एक मोनाड नहीं है।
  • एक प्रकार का कंस्ट्रक्टर जो एक मोनाड है।

मुझे लगता है कि हर जगह मोनाद के बहुत सारे उदाहरण हैं, लेकिन पिछले उदाहरणों के संबंध में मोनाद का एक अच्छा उदाहरण तस्वीर को पूरा कर सकता है।

मैं उन उदाहरणों की तलाश करता हूं जो एक-दूसरे के समान होंगे, विशेष प्रकार के वर्ग से संबंधित महत्वपूर्ण पहलुओं में भिन्न होते हैं।

अगर कोई इस पदानुक्रम में कहीं तीर का एक उदाहरण लेने का प्रबंधन कर सकता है (क्या यह लागू और मोनाड के बीच है?), तो यह बहुत अच्छा होगा!


4
क्या एक प्रकार का निर्माण करना संभव है ( * -> *) जिसके लिए कोई उपयुक्त नहीं हैfmap ?
ओवेन

1
ओवेन, मुझे लगता a -> Stringहै कि कोई फ़नकार नहीं है।
रॉटस्टर

3
@ रॉटर्स @ ओवेन a -> Stringएक गणितीय फ़नकार है, लेकिन Functorस्पष्ट होने के लिए हास्केल नहीं है ।
जे। अब्राहमसन

@जे। अब्राहमसन, किस अर्थ में गणितीय फ़नकार है? क्या आप उलटे तीर वाले श्रेणी की बात कर रहे हैं?
21

3
लोगों को पता नहीं है, एक contravariant functor में एक प्रकार का (a -> b) -> f b -> f a
फेम है

जवाबों:


100

एक प्रकार का कंस्ट्रक्टर जो फ़नकार नहीं है:

newtype T a = T (a -> Int)

आप इसमें से एक कंट्रावेरेंट फ़ंक्टर बना सकते हैं, लेकिन एक (कोवरिएन्ट) फ़ंक्टर नहीं। लिखने का प्रयास करें fmapऔर आप असफल होंगे। ध्यान दें कि कंट्रावेरिएंट फ़ंक्टर संस्करण उलटा है:

fmap      :: Functor f       => (a -> b) -> f a -> f b
contramap :: Contravariant f => (a -> b) -> f b -> f a

एक प्रकार का कंस्ट्रक्टर जो एक फ़नकार है, लेकिन लागू नहीं:

मेरे पास एक अच्छा उदाहरण नहीं है। वहाँ है Const, लेकिन आदर्श रूप से मुझे एक ठोस गैर-मोनॉइड चाहिए और मैं किसी के बारे में नहीं सोच सकता। जब आप इसके नीचे आते हैं तो सभी प्रकार मूल रूप से संख्यात्मक, गणना, उत्पाद, रकम या फ़ंक्शन होते हैं। आप नीचे कबूतर को देख सकते हैं और मैं इस बारे में असहमत हूं कि क्या Data.VoidMonoid;

instance Monoid Data.Void where
    mempty = undefined
    mappend _ _ = undefined
    mconcat _ = undefined

चूंकि _|_हास्केल में एक कानूनी मूल्य है, और वास्तव में इसका एकमात्र कानूनी मूल्य है Data.Void, यह मोनॉयड नियमों को पूरा करता है। मैं अनिश्चित हूं कि इसका क्या unsafeCoerceकरना है, क्योंकि आपका कार्यक्रम अब गारंटी नहीं है कि आप किसी भी unsafeफ़ंक्शन का उपयोग करते समय हास्केल शब्दार्थों का उल्लंघन न करें ।

नीचे ( लिंक ) या असुरक्षित कार्यों ( लिंक ) पर एक लेख के लिए हास्केल विकी देखें ।

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

एक प्रकार का कंस्ट्रक्टर जो एक आवेदक है, लेकिन एक मोनाड नहीं:

newtype T a = T {multidimensional array of a}

आप कुछ इस तरह से, इससे बाहर एक आवेदन कर सकते हैं:

mkarray [(+10), (+100), id] <*> mkarray [1, 2]
  == mkarray [[11, 101, 1], [12, 102, 2]]

लेकिन अगर आप इसे एक सनक बनाते हैं, तो आपको एक आयाम बेमेल मिल सकता है। मुझे संदेह है कि इस तरह के उदाहरण व्यवहार में दुर्लभ हैं।

एक प्रकार का निर्माण जो एक मोनाड है:

[]

तीर के बारे में:

यह पूछना कि एक तीर इस पदानुक्रम पर कहाँ है, यह पूछना कि "लाल" किस प्रकार का है। ध्यान दें बेमेल:

Functor :: * -> *
Applicative :: * -> *
Monad :: * -> *

परंतु,

Arrow :: * -> * -> *

3
अच्छी सूची! मैं Either aअंतिम मामले के लिए उदाहरण के रूप में कुछ सरल का उपयोग करने का सुझाव दूंगा , क्योंकि यह समझना आसान है।
फ़ुज

6
यदि आप अभी भी एक प्रकार के निर्माता की तलाश कर रहे हैं जो कि लागू हो लेकिन एक मोनाड नहीं है, तो एक बहुत ही सामान्य उदाहरण होगा ZipList
जॉन एल

23
_|_* में हर प्रकार का निवास करता है, लेकिन यह है Voidकि आपको एक निर्माण करने के लिए पीछे की ओर झुकना चाहिए या आपने इसके मूल्य को नष्ट कर दिया है। यही कारण है कि अपने Enum, monoid, आदि की नहीं एक उदाहरण तो आपके पास पहले से, मैं आप उन्हें एक साथ मैश जाने के लिए खुश हूँ (यदि आप एक दे रही है Semigroup), लेकिन mempty, लेकिन मैं स्पष्ट रूप से प्रकार का एक मूल्य के निर्माण के लिए कोई उपकरण देने Voidमें void। आपको बंदूक को लोड करना होगा और इसे अपने पैर पर इंगित करना होगा और ट्रिगर को स्वयं खींचना होगा।
एडवर्ड KMETT

2
गंभीर रूप से, मुझे लगता है कि कॉफुनक्टर की आपकी धारणा गलत है। एक फ़नकार का दोहरी एक फ़नकार है, क्योंकि आप इनपुट और आउटपुट दोनों को फ्लिप करते हैं और बस एक ही चीज़ के साथ समाप्त होते हैं। आप जिस धारणा की तलाश कर रहे हैं, वह संभवतः "कॉन्ट्रैवियरेंट फ़ंक्टर" है, जो थोड़ा अलग है।
बेन मिलवुड

1
@AlexVong: "पदावनत" -> लोग सिर्फ एक अलग पैकेज का उपयोग कर रहे हैं। "Contravariant functor" के बारे में बात करने से "functor का दोहरापन" नहीं होता, भ्रम की स्थिति के लिए खेद है। कुछ संदर्भों में मैंने "कॉफ़नक्टर" का उपयोग "कॉन्ट्रैवारेंट फ़ंक्शनलर्स" को संदर्भित करने के लिए किया है क्योंकि फंक्शंस स्वयं-दोहरे हैं, लेकिन यह लोगों को भ्रमित करने के लिए प्रतीत होता है।
डिट्रीच एप ईपी

87

मेरी शैली मेरे फोन से तंग हो सकती है, लेकिन यहाँ जाता है।

newtype Not x = Kill {kill :: x -> Void}

एक फ़नकार नहीं हो सकता। अगर ऐसा होता, तो हमारे पास होता

kill (fmap (const ()) (Kill id)) () :: Void

और चंद्रमा हरी चीज़ से बना होगा।

इस दौरान

newtype Dead x = Oops {oops :: Void}

एक फनकार है

instance Functor Dead where
  fmap f (Oops corpse) = Oops corpse

लेकिन लागू नहीं किया जा सकता है, या हम होगा

oops (pure ()) :: Void

और ग्रीन मून पनीर से बना होगा (जो वास्तव में हो सकता है, लेकिन केवल शाम को बाद में)।

(अतिरिक्त नोट:, Voidजैसा Data.Voidकि एक खाली डेटाटाइप है। यदि आप undefinedइसे एक मोनॉइड साबित करने के लिए उपयोग करने का प्रयास करते हैं , तो मैं unsafeCoerceयह साबित करने के लिए उपयोग करूंगा कि यह नहीं है।)

आनंद से,

newtype Boo x = Boo {boo :: Bool}

कई तरह से प्रयोजनीय है, उदाहरण के लिए, जैसा कि दिज्क्स्ट्रा के पास होता है,

instance Applicative Boo where
  pure _ = Boo True
  Boo b1 <*> Boo b2 = Boo (b1 == b2)

लेकिन यह एक मोनाड नहीं हो सकता। यह देखने के लिए कि क्यों नहीं, निरीक्षण करें कि वापसी लगातार Boo Trueया Boo False, और इसलिए होनी चाहिए

join . return == id

संभवतः पकड़ नहीं सकता।

अरे हाँ, मैं लगभग भूल गया था

newtype Thud x = The {only :: ()}

एक मोनाड है। अपना खुद का रोल करें।

पकड़ने की योजना ...


8
शून्य खाली है! नैतिक रूप से, किसी भी तरह।
सुअर का बच्चा

9
शून्य 0 कंस्ट्रक्टर्स के साथ एक प्रकार है, मुझे लगता है। यह एक मोनॉयड नहीं है क्योंकि वहाँ नहीं है mempty
रॉस्टर

6
अपरिभाषित? कैसे अशिष्ट हैं! अफसोस की बात है, असुरक्षित (असुरक्षित) () <*> अपरिभाषित) नहीं है (), इसलिए वास्तविक जीवन में, ऐसे अवलोकन हैं जो कानूनों का उल्लंघन करते हैं।
सुअर का बच्चा

5
सामान्य शब्दार्थ में, जो बिल्कुल एक तरह के अपरिभाषित को सहन करता है, आप काफी सही हैं। अन्य शब्दार्थ हैं, अवश्य। शून्य कुल अंश में एक सबमोनॉइड तक सीमित नहीं है। न ही यह एक शब्दार्थ में एक मोनॉइड है जो विफलता के तरीकों को अलग करता है। जब मेरे पास फोन-आधारित संपादन की तुलना में आसान क्षण होता है, तो मैं स्पष्ट करता हूं कि मेरा उदाहरण केवल शब्दार्थ में काम करता है, जिसके लिए एक प्रकार का अपरिभाषित नहीं है।
सूअर का बच्चा

22
बहुत कुछ के बारे में_|_
Landei

71

मेरा मानना ​​है कि अन्य उत्तर कुछ सरल और सामान्य उदाहरणों से चूक गए:

एक प्रकार का कंस्ट्रक्टर जो एक फ़नकार है, लेकिन एक आवेदक नहीं है। एक सरल उदाहरण एक जोड़ी है:

instance Functor ((,) r) where
    fmap f (x,y) = (x, f y)

लेकिन Applicativeअतिरिक्त प्रतिबंध लगाए बिना इसके उदाहरण को परिभाषित करने का कोई तरीका नहीं है r। विशेष रूप से, कोई तरीका नहीं है कि कैसे pure :: a -> (r, a)एक मनमाना के लिए परिभाषित किया जाए r

एक प्रकार का कंस्ट्रक्टर जो एक एपेक्टिव है, लेकिन एक मोनाड नहीं है। एक प्रसिद्ध उदाहरण जिपलिस्ट है । (यह एक newtypeसूची है जो सूचियों को लपेटता है और Applicativeउनके लिए विभिन्न उदाहरण प्रदान करता है।)

fmapसामान्य तरीके से परिभाषित किया गया है। लेकिन pureऔर के <*>रूप में परिभाषित कर रहे हैं

pure x                    = ZipList (repeat x)
ZipList fs <*> ZipList xs = ZipList (zipWith id fs xs)

इसलिए pureदिए गए मान को दोहराकर एक अनंत सूची बनाता है, और <*>मूल्यों की सूची के साथ कार्यों की एक सूची ज़िप करता है - i -th फ़ंक्शन को i -th तत्व पर लागू करता है । (मानक <*>पर []लागू करने के सभी संभव संयोजनों का उत्पादन मैं करने के लिए मई के समारोह जे वें तत्व।) लेकिन कोई समझदार तरीका है कि कैसे एक इकाई (देखें परिभाषित करने के लिए है इस पोस्ट )।


फ़नकार / एपेरेटिव / मोनाड पदानुक्रम में तीर कैसे फिट होते हैं? देखें कि मुहावरे अनजान हैं, तीर सावधानी से, मोन लिंडले सैम लिंडले, फिलिप वाडलर, जेरेमी यलोप द्वारा प्रचारित हैं। MSFP 2008. (वे एप्लाइड फंक्शनलर्स मुहावरों को कहते हैं ।) सार:

हम अभिकलन की तीन धारणाओं के बीच संबंध पर फिर से गौर करते हैं: मोगी के मोनैड्स, ह्यूजेस के तीर और मैकब्राइड और पैटर्सन के मुहावरे (जिसे ऐप्लिकेटिव फ़ंक्शंस भी कहा जाता है)। हम दिखाते हैं कि मुहावरे ऐसे तीर के बराबर होते हैं जो प्रकार के समरूपतावाद को संतुष्ट करते हैं A ~> B = 1 ~> (A -> B) और यह कि तीर तीर के समकक्ष हैं जो प्रकार के समरूपता को संतुष्ट करते हैं A ~> B = A> (1 ~) > बी)। इसके अलावा, मुहावरे बाणों में बाण मारते हैं और बाण मुनियों में प्रवृत्त होते हैं।


1
तो ((,) r)एक ऐसा फन्नेकार है जो एक आवेदक नहीं है; लेकिन यह केवल इसलिए है क्योंकि आप आम तौर पर एक बार में pureसभी के लिए परिभाषित नहीं कर सकते हैं r। इसलिए यह में से एक परिभाषा के साथ अनुप्रयोगी functors के एक (अनंत) संग्रह को परिभाषित करने की कोशिश कर की भाषा संक्षिप्तता के एक मोड़ है, pureऔर <*>; इस अर्थ में, इस काउंटर-उदाहरण के बारे में गणितीय रूप से कुछ भी गहरा नहीं लगता है, क्योंकि किसी भी कंक्रीट के लिए r, एक आवेदक अंतिम संस्कार किया ((,) r) जा सकता है। प्रश्न: क्या आप एक CONCRETE फ़नकार के बारे में सोच सकते हैं जो एक आवेदक होने में विफल रहता है?
जॉर्ज

1
इस सवाल के साथ stackoverflow.com/questions/44125484/… पोस्ट के रूप में देखें ।
जॉर्ज

20

एक प्रकार के कंस्ट्रक्टर के लिए एक अच्छा उदाहरण जो कि एक फ़नकार नहीं है Set: आप लागू नहीं कर सकते fmap :: (a -> b) -> f a -> f b, क्योंकि अतिरिक्त बाधा के बिना Ord bआप निर्माण नहीं कर सकते f b


16
यह वास्तव में एक अच्छा उदाहरण है क्योंकि गणितीय रूप से हम वास्तव में इसे एक मज़ेदार बनाना चाहेंगे।
अलेक्जेंड्रे सी।

21
@AlexandreC। मैं उस पर असहमत हूँ, यह एक अच्छा उदाहरण नहीं है। गणितीय रूप से, ऐसी डेटा संरचना एक फ़नकार का निर्माण करती है। तथ्य यह है कि हम लागू नहीं कर सकते हैं fmapसिर्फ एक भाषा / कार्यान्वयन मुद्दा है। इसके अलावा, Setनिरंतरता वाले सनक में लपेटना संभव है , जो हमारे द्वारा अपेक्षित सभी गुणों के साथ एक मोनाड बनाता है, इस प्रश्न को देखें (हालांकि मुझे यकीन नहीं है कि यह कुशलतापूर्वक किया जा सकता है)।
पेट्र पुडलक 17

@PetrPudlak, यह एक भाषा का मुद्दा कैसे है? bहो सकता है कि आप इसे परिभाषित न कर सकें, उस स्थिति में समानता अविश्वसनीय हो सकती है fmap!
Turion

@Turion निर्णायक और निश्चित होने के नाते दो अलग चीजें हैं। उदाहरण के लिए लैंबडा टर्म्स (प्रोग्राम्स) पर समानता को सही ढंग से परिभाषित करना संभव है, भले ही इसे एल्गोरिथम द्वारा तय करना संभव न हो। किसी भी मामले में, यह इस उदाहरण का मामला नहीं था। यहाँ समस्या यह है कि हम बाधा के Functorसाथ एक उदाहरण को परिभाषित नहीं कर सकते हैं Ord, लेकिन यह एक अलग परिभाषा Functorया बेहतर भाषा समर्थन के साथ संभव हो सकता है । वास्तव में कांस्ट्रेक्टकिंड के साथ एक प्रकार के वर्ग को परिभाषित करना संभव है जो इस तरह से पैरामीट्रिक हो सकता है।
पेट्र पुडलक

यहां तक ​​कि अगर हम ordइस तथ्य को दूर Setकर सकते हैं कि डुप्लिकेट प्रविष्टियों को शामिल नहीं किया जा fmapसकता है, तो इसका मतलब है कि संदर्भ को वेदी कर सकते हैं। यह सहकारिता कानून का उल्लंघन करता है।
जॉन एफ। मिलर

11

मैं इस प्रश्न का उत्तर देने के लिए एक अधिक व्यवस्थित दृष्टिकोण का प्रस्ताव करना चाहता हूं, और ऐसे उदाहरण भी दिखाना चाहता हूं जो "नीचे" मान या अनंत डेटा प्रकार या उस जैसे कुछ भी विशेष चाल का उपयोग न करें।

टाइप कंस्ट्रक्टर कब टाइप करने के लिए असफल होते हैं?

सामान्य तौर पर, दो प्रकार के कारण एक प्रकार के निर्माणकर्ता एक निश्चित प्रकार के वर्ग की आवृत्ति के लिए असफल हो सकते हैं:

  1. प्रकार वर्ग से आवश्यक विधियों के प्रकार हस्ताक्षर को लागू नहीं कर सकते।
  2. प्रकार के हस्ताक्षर लागू कर सकते हैं लेकिन आवश्यक कानूनों को पूरा नहीं कर सकते।

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

विशिष्ट उदाहरण

  • एक प्रकार का कंस्ट्रक्टर जिसमें फ़नकार का उदाहरण नहीं हो सकता है क्योंकि वह प्रकार लागू नहीं किया जा सकता है:

    data F z a = F (a -> z)

यह एक कॉन्ट्रैक्टर है, न कि किसी फंक्शनलर के साथ, टाइप पैरामीटर के संबंध में a, क्योंकि aएक कॉन्ट्रैवियरी स्थिति में है। प्रकार हस्ताक्षर के साथ एक फ़ंक्शन को लागू करना असंभव है (a -> b) -> F z a -> F z b

  • एक प्रकार का कंस्ट्रक्टर, जो कानूनन फ़नकार नहीं है, भले ही उसके प्रकार के हस्ताक्षर fmapलागू किए जा सकते हैं:

    data Q a = Q(a -> Int, a)
    fmap :: (a -> b) -> Q a -> Q b
    fmap f (Q(g, x)) = Q(\_ -> g x, f x)  -- this fails the functor laws!

इस उदाहरण का जिज्ञासु पहलू यह है कि हम सही प्रकार का कार्यान्वयन कर सकते हैं fmap, भले ही Fसंभवतः एक फ़नकार नहीं हो सकता है क्योंकि यह aएक कंट्राविरेंट स्थिति में उपयोग करता है। तो fmapऊपर दिखाया गया यह कार्यान्वयन भ्रामक है - भले ही इसके पास सही प्रकार के हस्ताक्षर हों (मेरा मानना ​​है कि यह उस प्रकार के हस्ताक्षर का एकमात्र संभव कार्यान्वयन है), फ़नकार कानून संतुष्ट नहीं हैं। उदाहरण के लिए, fmap idid, क्योंकि let (Q(f,_)) = fmap id (Q(read,"123")) in f "456"है 123, लेकिन let (Q(f,_)) = id (Q(read,"123")) in f "456"है 456

वास्तव में, Fकेवल एक प्रोफेसर है, - यह न तो एक फनकार है और न ही एक कॉन्ट्रैक्टर है।

  • एक कानूनन फ़नकार जो लागू नहीं होता है क्योंकि उस प्रकार के हस्ताक्षर को pureलागू नहीं किया जा सकता है: राइटर मोनाड को लें (a, w)और wएक मोहरा होना चाहिए कि बाधा को हटा दें । इसके बाद (a, w)बाहर से मूल्य का निर्माण करना असंभव है a

  • एक फ़नकार जो कि आवेदक नहीं है क्योंकि उस प्रकार के हस्ताक्षर को <*>लागू नहीं किया जा सकता है data F a = Either (Int -> a) (String -> a):।

  • एक फ़नकार जो क़ानूनी रूप से लागू नहीं है, भले ही टाइप क्लास के तरीके लागू किए जा सकते हैं:

    data P a = P ((a -> Int) -> Maybe a)

टाइप कंस्ट्रक्टर Pएक फन्नेकार है क्योंकि यह aकेवल सहसंयोजक पदों में उपयोग करता है ।

instance Functor P where
   fmap :: (a -> b) -> P a -> P b
   fmap fab (P pa) = P (\q -> fmap fab $ pa (q . fab))

के प्रकार के हस्ताक्षर का एकमात्र संभावित कार्यान्वयन <*>एक ऐसा कार्य है जो हमेशा लौटता है Nothing:

 (<*>) :: P (a -> b) -> P a -> P b
 (P pfab) <*> (P pa) = \_ -> Nothing  -- fails the laws!

लेकिन यह कार्यान्वयन आवेदक फंक्शनलर्स के लिए पहचान कानून को संतुष्ट नहीं करता है।

  • एक फ़नकार जो कि ऐसा Applicativeनहीं है,Monad क्योंकि टाइप हस्ताक्षर bindलागू नहीं किया जा सकता है।

मैं ऐसे किसी भी उदाहरण को नहीं जानता!

  • एक फ़नकार जो कि ऐसा Applicativeनहीं है,Monad क्योंकि एक क़ानून को संतुष्ट नहीं किया जा सकता, भले ही उस प्रकार के हस्ताक्षर को bindलागू किया जा सके।

इस उदाहरण ने काफी चर्चा पैदा की है, इसलिए यह कहना सुरक्षित है कि इस उदाहरण को सही साबित करना आसान नहीं है। लेकिन कई लोगों ने अलग-अलग तरीकों से इसे स्वतंत्र रूप से सत्यापित किया है। देखें `डेटा पीओई ए = खाली | जोड़ी आ` मोनाद? अतिरिक्त चर्चा के लिए।

 data B a = Maybe (a, a)
   deriving Functor

 instance Applicative B where
   pure x = Just (x, x)
   b1 <*> b2 = case (b1, b2) of
     (Just (x1, y1), Just (x2, y2)) -> Just((x1, x2), (y1, y2))
     _ -> Nothing

यह साबित करना थोड़ा बोझिल है कि कोई कानूनन Monadउदाहरण नहीं है। गैर-मौद्रिक व्यवहार का कारण यह है कि bindजब कोई फ़ंक्शन f :: a -> B bवापस आ सकता है Nothingया Justविभिन्न मूल्यों के लिए लागू करने का कोई प्राकृतिक तरीका नहीं है a

यह विचार करना शायद स्पष्ट है Maybe (a, a, a), जो एक सन्यासी भी नहीं है, और इसके लिए कार्यान्वयन करने का प्रयास करना joinहै। कोई यह पाएगा कि लागू करने का कोई सहज तरीका नहीं है join

 join :: Maybe (Maybe (a, a, a), Maybe (a, a, a), Maybe (a, a, a)) -> Maybe (a, a, a)
 join Nothing = Nothing
 join Just (Nothing, Just (x1,x2,x3), Just (y1,y2,y3)) = ???
 join Just (Just (x1,x2,x3), Nothing, Just (y1,y2,y3)) = ???
 -- etc.

द्वारा इंगित मामलों में ???, यह स्पष्ट लगता है कि हम Just (z1, z2, z3)छह अलग-अलग प्रकार के मूल्यों में से किसी भी उचित और सममित तरीके से उत्पादन नहीं कर सकते हैं a। हम निश्चित रूप से इन छह मूल्यों में से कुछ मनमाना उपसमुच्चय चुन सकते हैं, उदाहरण के लिए, हमेशा पहली गैर Maybe- रिक्तता लें - लेकिन यह मठ के कानूनों को संतुष्ट नहीं करेगा। लौटना Nothingभी कानूनों को संतुष्ट नहीं करेगा।

  • एक पेड़ की तरह डेटा संरचना जो एक सन्यासी नहीं है, भले ही इसके लिए सहानुभूति हो bind- लेकिन पहचान कानूनों को विफल करता है।

सामान्य वृक्ष के समान मोनाड (या "फ़नकार के आकार की शाखाओं वाला वृक्ष") के रूप में परिभाषित किया गया है

 data Tr f a = Leaf a | Branch (f (Tr f a))

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

यदि हम इस डेटा संरचना को fफंक्शनल के आकार में भी बनाकर संशोधित करते हैं , तो हम उसे "सेमिमोनड" कहते हैं - bindजो कि स्वाभाविकता और सहानुभूति कानूनों को संतुष्ट करता है, लेकिन इसकी pureविधि पहचान कानूनों में से एक को विफल करती है। "सेमीमोनड एंडोफ़ुन्क्टरों की श्रेणी में अर्धवृत्त हैं, समस्या क्या है?" यह प्रकार वर्ग है Bind

सादगी के लिए, मैं joinइसके बजाय विधि को परिभाषित करता हूं bind:

 data Trs f a = Leaf (f a) | Branch (f (Trs f a))
 join :: Trs f (Trs f a) -> Trs f a
 join (Leaf ftrs) = Branch ftrs
 join (Branch ftrstrs) = Branch (fmap @f join ftrstrs)

शाखा ग्राफ्टिंग मानक है, लेकिन पत्ती ग्राफ्टिंग गैर मानक है और एक उत्पादन करती है Branch। यह संबद्धता कानून के लिए कोई समस्या नहीं है, लेकिन पहचान कानूनों में से एक को तोड़ देता है।

बहुपद के प्रकार कब होते हैं?

न तो फंक्शनलर्स Maybe (a, a)और न ही Maybe (a, a, a)उन्हें कोई कानूनी Monadउदाहरण दिया जा सकता है , हालांकि वे स्पष्ट रूप से हैं Applicative

कोई - ये functors कोई चाल है Voidया bottomकहीं भी, कोई मुश्किल आलस्य / कठोरता, कोई अनंत संरचनाओं, और कोई प्रकार वर्ग की कमी। Applicativeउदाहरण के लिए पूरी तरह से मानक है। फ़ंक्शंस returnऔर bindइन फंक्शनलर्स के लिए लागू किया जा सकता है लेकिन मोनाड के कानूनों को संतुष्ट नहीं करेगा। दूसरे शब्दों में, ये फ़ंक्शनलर्स मोनड्स नहीं हैं क्योंकि एक विशिष्ट संरचना गायब है (लेकिन यह समझना आसान नहीं है कि वास्तव में क्या गायब है)। एक उदाहरण के रूप में, फ़नकार में एक छोटा परिवर्तन इसे एक सनक में बना सकता है: data Maybe a = Nothing | Just aएक सन्यासी है। इसी तरह का एक अन्य फ़नकार data P12 a = Either a (a, a)भी एक सन्यासी है।

बहुपद संन्यासियों के लिए निर्माण

सामान्य तौर पर, यहां कुछ निर्माण हैं जो Monadबहुपद प्रकारों से वैध एस का उत्पादन करते हैं। इन सभी निर्माणों में, Mएक मठ है:

  1. type M a = Either c (w, a)wकोई भी मोनोड कहां है
  2. type M a = m (Either c (w, a))जहां mकोई भी साधु है और wकोई भी भिक्षु है
  3. type M a = (m1 a, m2 a)कहाँ m1और m2कोई भी सन्यासी हैं
  4. type M a = Either a (m a)जहां mकिसी भी इकाई है

पहला निर्माण है WriterT w (Either c), दूसरा निर्माण है WriterT w (EitherT c m)। तीसरे निर्माण monads के एक घटक के लिहाज से उत्पाद है: pure @Mके घटक-वार उत्पाद के रूप में परिभाषित किया गया है pure @m1और pure @m2, और join @Mपार उत्पाद डेटा को छोड़ते हुए (जैसे द्वारा परिभाषित किया गया है m1 (m1 a, m2 a)करने के लिए मैप किया गया है m1 (m1 a)टपल के दूसरे भाग को छोड़ते हुए से):

 join :: (m1 (m1 a, m2 a), m2 (m1 a, m2 a)) -> (m1 a, m2 a)
 join (m1x, m2x) = (join @m1 (fmap fst m1x), join @m2 (fmap snd m2x))

चौथे निर्माण के रूप में परिभाषित किया गया है

 data M m a = Either a (m a)
 instance Monad m => Monad M m where
    pure x = Left x
    join :: Either (M m a) (m (M m a)) -> M m a
    join (Left mma) = mma
    join (Right me) = Right $ join @m $ fmap @m squash me where
      squash :: M m a -> m a
      squash (Left x) = pure @m x
      squash (Right ma) = ma

मैंने जाँच की है कि सभी चार निर्माण वैध भिक्षुओं का उत्पादन करते हैं।

मैं अनुमान लगाता हूं कि बहुपद मठों के लिए कोई अन्य निर्माण नहीं हैं। उदाहरण के लिए, फ़नकार Maybe (Either (a, a) (a, a, a, a))को इनमें से किसी भी निर्माण के माध्यम से प्राप्त नहीं किया जाता है और इसलिए यह अस्वच्छ नहीं है। हालांकि, Either (a, a) (a, a, a)क्योंकि यह तीन monads के उत्पाद isomorphic को है monadic है a, a, और Maybe a। इसके अलावा, Either (a,a) (a,a,a,a)क्योंकि इसके बारे में उत्पाद isomorphic को है monadic है aऔर Either a (a, a, a)

ऊपर दिखाए गए चार निर्माण हमें किसी भी संख्या के किसी भी उत्पाद के किसी भी राशि को प्राप्त करने की अनुमति देंगे a, उदाहरण के लिए Either (Either (a, a) (a, a, a, a)) (a, a, a, a, a))और इसी तरह। ऐसे सभी प्रकार के निर्माणकर्ताओं के पास (कम से कम एक) Monadउदाहरण होगा।

यह देखा जाना चाहिए, निश्चित रूप से, ऐसे साधुओं के लिए कौन से उपयोग के मामले मौजूद हो सकते हैं। एक और मुद्दा यह है कि Monad1-4 निर्माण के माध्यम से प्राप्त उदाहरण सामान्य रूप से अद्वितीय नहीं हैं। उदाहरण के लिए, टाइप कंस्ट्रक्टर type F a = Either a (a, a)को Monadदो तरीकों से एक उदाहरण दिया जा सकता है: निर्माण 4 में मोनड का उपयोग करके (a, a), और निर्माण 3 का उपयोग आइसोमॉर्फिज्म द्वारा किया जाता है Either a (a, a) = (a, Maybe a)। फिर, इन कार्यान्वयनों के लिए उपयोग के मामलों को खोजना तुरंत स्पष्ट नहीं है।

एक सवाल बना हुआ है - एक मनमाना बहुपद डेटा प्रकार दिया गया है, यह कैसे पहचाना जाए कि उसका कोई Monadउदाहरण है। मुझे नहीं पता कि कैसे साबित करना है कि बहुपद मोनाड्स के लिए कोई अन्य निर्माण नहीं हैं। मुझे नहीं लगता कि इस प्रश्न का उत्तर देने के लिए कोई सिद्धांत अभी तक मौजूद है।


मुझे लगता B है कि एक सन्यासी है। क्या आप इस बाइंड को एक प्रतिरूप दे सकते हैं Pair x y >>= f = case (f x, f y) of (Pair x' _,Pair _ y') -> Pair x' y' ; _ -> Empty?
फ्रैंकी

@ फ्रेंकी एसोसिएटिविटी इस परिभाषा के साथ विफल हो जाती है जब आप ऐसा चुनते fहैं f x, Emptyलेकिन f yएक है Pair, और अगले चरण पर दोनों हैं Pair। मैंने हाथ से जाँच की कि कानून इस कार्यान्वयन के लिए या किसी अन्य कार्यान्वयन के लिए नहीं हैं। लेकिन ऐसा करना काफी हद तक सही है। काश, यह पता लगाने का एक आसान तरीका होता!
winitzki

1
@ यह तर्क Maybeइसलिए लागू नहीं होता क्योंकि Maybeइसमें aचिंता करने के विभिन्न मूल्य नहीं होते हैं।
डैनियल वैगनर

1
@ अनुमान मैंने गणना के कुछ पृष्ठों के द्वारा इसे साबित किया है; "प्राकृतिक तरीके" के बारे में तर्क सिर्फ एक व्याख्यात्मक व्याख्या है। एक Monadउदाहरण में कार्य होते हैं returnऔर bindजो कानूनों को संतुष्ट करते हैं। के दो कार्यान्वयन returnऔर 25 कार्यान्वयन bindआवश्यक प्रकार के होते हैं। आप प्रत्यक्ष गणना द्वारा दिखा सकते हैं कि कार्यान्वयन में से कोई भी कानूनों को संतुष्ट नहीं करता है। आवश्यक काम की राशि में कटौती करने के लिए, मैं प्रयोग किया जाता है joinके बजाय bindऔर पहली पहचान कानूनों का इस्तेमाल किया। लेकिन यह काम का एक उचित सा रहा है।
winitzki

1
@ डुप्लोड नहीं, मुझे नहीं लगता कि Traversableइसकी आवश्यकता है। m (Either a (m a))में बदल रहा pure @mहै m (Either (m a) (m a))। फिर तुच्छ Either (m a) (m a) -> m a, और हम उपयोग कर सकते हैं join @m। यह वह कार्यान्वयन था जिसके लिए मैंने कानूनों की जाँच की।
winitzki
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.