2011-01-22 11 views
30

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

यह मोनड प्रदर्शन किए गए बाइंडों की संख्या की गणना करता है।

data C a = C {value :: a, count :: Int} deriving (Show) 

instance Monad C where 
    (>>=) (C x c) f = C (value $ f x) (c + 1) 
    return x = C x 0 

add :: (Num a) => a -> a -> C a 
add x y = return $ x + y 

-- Simpler way to do this? foldM is obviously something different. 
mysum [x] = return x 
mysum (x:xs) = mysum xs >>= add x 

उत्तर

88

स्टाइलिस्टिक रूप से यह बहुत अच्छा है। असली दुनिया में, मैं बजाय एक आप दे दी है की इस अंकन की एक 60% मौका उम्मीद करेंगे:

C x c >>= f = C (value $ f x) (c + 1) 

लेकिन वह यह शायद ही उल्लेख के लायक है, तो ही कम हो।

एक और गंभीर नोट पर, स्टाइलिस्ट नहीं बल्कि अर्थपूर्ण: यह एक मोनड नहीं है। वास्तव में, यह सभी तीन मोनैड कानूनों का उल्लंघन करता है।

(1) return x >>= f = f x 
(2) m >>= return = m 
(3) m >>= (f >=> g) = (m >>= f) >>= g 

(कहाँ (>=>)f >=> g = \x -> f x >>= g के रूप में परिभाषित किया गया है। (>>=) "एप्लिकेशन" ऑपरेटर माना जाता है, तो (>=>) इसी रचना ऑपरेटर है। मैं तीसरे नियम इस ऑपरेटर का उपयोग राज्य के लिए है क्योंकि यह बाहर लाता तीसरे नियम के पसंद अर्थ: संबद्धता)

इन गणनाओं के साथ

:।

(1):

return 0 >>= return 
    = C 0 0 >>= return 
    = C (value $ return 0) 1 
    = C 0 1 
Not equal to return 0 = C 0 0 

(2):

C 0 0 >>= return 
    = C (value $ return 0) 1 
    = C 0 1 
Not equal to C 0 0 

(3)

C 0 0 >>= (return >=> return) 
    = C (value $ (return >=> return) 0) 1 
    = C (value $ return 0 >>= return) 1 
    = C (value $ C 0 1) 1 
    = C 0 1 

Is not equal to: 

(C 0 0 >>= return) >>= return 
    = C (value $ return 0) 1 >>= return 
    = C 0 1 >>= return 
    = C (value $ return 0) 2 
    = C 0 2 

यह सिर्फ अपने कार्यान्वयन में कोई त्रुटि नहीं है - कोई इकाई है कि "बांध के संख्या की गणना" है। यह कानूनों का उल्लंघन (1) और (2) होना चाहिए। तथ्य यह है कि आपका कानून कानून (3) का उल्लंघन करता है, हालांकि एक कार्यान्वयन त्रुटि है।

समस्या यह है कि f(>>=) की परिभाषा में एक क्रिया को वापस कर सकता है जिसमें एक से अधिक बांध हैं, और आप इसे अनदेखा कर रहे हैं। आप की जरूरत छोड़ दिया और सही तर्कों से जोड़ने बांध के नंबर:

C x c >>= f = C y (c+c'+1) 
    where 
    C y c' = f x 

यह सही ढंग से बांध के संख्या की गिनती होगी, और तीसरा कानून है, जो संबद्धता कानून है को संतुष्ट करेगा। यह दूसरे दो को संतुष्ट नहीं करेगा। हालांकि, अगर आप इस परिभाषा से +1 छोड़ते हैं, तो आप एक वास्तविक मोनैड प्राप्त करें, जो मोनॉयड + मोनॉयड पर है। यह मूल रूप से सभी सबकंप्यूशन के परिणामों को जोड़ता है। आप somethings की संख्या गिनने के लिए इसका उपयोग कर सकते हैं, बस बाध्य नहीं है - बंधन गिनने के लिए बहुत खास है। लेकिन, उदाहरण के लिए:

tick :: C() 
tick = C() 1 

फिर Ctick कि गणना में हुई की संख्या की गिनती होगी।

वास्तव में, यदि आप किसी भी साहचर्य ऑपरेटर के साथ किसी भी प्रकार से Int और (+) की जगह और एक इकाई मिल सकती है। यह Writer मोनड सामान्य रूप से है। यदि ऑपरेटर सहयोगी नहीं है, तो यह तीसरे कानून में विफल हो जाएगा (क्या आप देख सकते हैं क्यों?)।

+0

यह वही नहीं है जो मैं उम्मीद कर रहा था, लेकिन निश्चित रूप से मुझे जो चाहिए था। यदि ऑपरेटर सहयोगी नहीं है तो तीसरा कानून तोड़ दिया जाता है: क्योंकि तीसरा कानून बांध की साझेदारी है। यदि बाध्य "करता है" कुछ सहयोगी नहीं है (जहां मैं "करता है" की सटीक परिभाषा नहीं दे सकता), तो यह स्वयं भी सहयोगी नहीं हो सकता है। क्या वह सही है? – abesto

+10

इसके अलावा: सुंदर गहराई से स्पष्टीकरण। धन्यवाद। – abesto

+1

महान विस्तार से व्याख्या करने के लिए समय निकालने के लिए धन्यवाद! – Daniel

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