2011-10-20 13 views
7

मैं एक मोनैड के उदाहरण को निम्नानुसार परिभाषित कर रहा हूं:क्या हास्केल हमेशा जानता है कि कॉल करने के लिए कौन सा 'वापसी' है?

data Something = Something a 

instance Monad Something where 
    return a = Something a  --Wraps a in 'Something', correct? 
    m >>= f = do 
     var <- m 
     return $ f var   --I want this to pass var to f, then wrap the result 
            --back up in the 'Something' monad with the return I 
            --Just defined 

प्रश्न हैं ->

1: क्या मैं कर रहा हूं के साथ कोई चमकदार त्रुटियां/गलत धारणाएं हैं?

2: क्या हास्केल को उस m >>= f

3 से ऊपर परिभाषित रिटर्न को कॉल करना होगा: यदि मैं किसी कारण से किसी अन्य फ़ंक्शन को परिभाषित करता हूं

f :: Something a -> Something b 
f x = do 
    var <- x 
    return $ doMagicTo x 

return मैनेड में परिभाषित रिटर्न को कॉल करेगा Something में उदाहरण और लपेटें x?

उत्तर

15

यहां कुछ बड़ी समस्याएं हैं।

सबसे पहले, Monad उदाहरण में kind* -> * होना चाहिए। इसका मतलब है कि उन्हें कम से कम एक प्रकार परिवर्तनीय की आवश्यकता है, जहां आपके Something में कोई भी नहीं है। तुलना के लिए:

-- kind * -> * 
Maybe 
IO 
Either String 

-- kind * 
Maybe Int 
IO() 
Either String Double 

देखें करने से पहले उनका उपयोग कैसे कर सकते Maybe, IO, और Either String प्रत्येक एक प्रकार पैरामीटर की ज़रूरत है? Something के साथ, वहाँ प्रकार पैरामीटर में भरने के लिए कोई जगह नहीं है तो आप के लिए अपनी परिभाषा को बदलने की जरूरत:।

data Something a = Something a 

दूसरी बड़ी समस्या अपने इकाई उदाहरण में >>= गलत है। आप आमतौर पर डू-नोटेशन का उपयोग नहीं कर सकते क्योंकि यह केवल Monad फ़ंक्शंस return और >>= पर कॉल करता है। इसलिए आपको बिना किसी मोनैड फ़ंक्शंस के लिखना होगा, या तो >>= या return पर कॉल करना या कॉल करना होगा।

instance Monad Something where 
    return a = Something a  --Wraps a in 'Something' 
    (Something m) >>= f = f m  --unwraps m and applies it to f 

>>= की परिभाषा आपके अपेक्षा से सरल है। Unwrapping m आसान है क्योंकि आपको Something कन्स्ट्रक्टर पर पैटर्न-मिलान की आवश्यकता है। f :: a -> m b, इसलिए आपको इसे फिर से लपेटने की चिंता करने की आवश्यकता नहीं है, क्योंकि f आपके लिए यह करता है।

वहाँ सामान्य में एक इकाई खोलने में कोई रास्ता नहीं है, वहीं बहुत सारे विशिष्ट monads unwrapped जा सकता है।

ध्यान रखें कि मोनैड इंस्टेंस घोषणा में डू-नोटेशन या >>= का उपयोग करने के साथ वाक्य रचनात्मक रूप से गलत नहीं है। समस्या यह है कि >>= को संक्षेप में परिभाषित किया गया है ताकि जब आप इसे उपयोग करने का प्रयास करते हैं तो प्रोग्राम एक अंतहीन पाश में जाता है।

अपने तीसरे प्रश्न के लिए (N.B. Something के रूप में यहां बताए गए Identity monad है), हाँ return समारोह इकाई उदाहरण में परिभाषित किया गया है कि एक बुलाया जाएगा है। टाइप क्लास टाइप द्वारा प्रेषित होते हैं, और जैसा कि आपने निर्दिष्ट किया है कि प्रकार Something b होना चाहिए संकलक स्वचालित रूप से Something के लिए मोनाड इंस्टेंस का उपयोग करेगा। (मुझे लगता है कि आप doMagicTo var होने वाली अंतिम पंक्ति का मतलब है)।

+3

यह बहुत अच्छा है। ये सभी जवाब बहुत अच्छे हैं। मुझे यह टिप्पणी करने के लिए मजबूर होना पड़ता है कि हास्केल समुदाय अब तक का सबसे सहायक और पूरी तरह से सामना कर रहा है। चीयर्स गायस। – providence

2
  1. बंद करें। return यहां अनावश्यक है और आपको अपने Something प्रकार कन्स्ट्रक्टर में एक प्रकार पैरामीटर जोड़ने की आवश्यकता है। संपादित करें: यह कोड अभी भी गलत है। >>= की परिभाषा परिपत्र है। अधिक जानकारी के लिए अन्य उत्तरों देखें।

    data Something a = Something a 
    
    instance Monad Something where 
        return a = Something a 
        m >>= f = do 
         var <- m 
         f var 
    
  2. के बाद से >>= के लिए अपनी परिभाषा instance Monad Something where किया जा रहा है, >>= के प्रकार Something a -> (a -> Something b) -> Something b है। तो यह बता सकता है कि f var को Something b टाइप करना होगा। यहां Google को शब्द "टाइप अनुमान"

  3. हां है। फिर, यह प्रकार अनुमान है। यदि संकलक आपके इच्छित प्रकार का अनुमान नहीं लगा सकता है, तो यह आपको बताएगा। लेकिन आमतौर पर यह कर सकते हैं।

+0

जॉन एल का समाधान देखें: आप '>> =' को परिभाषित करने के लिए डू-ब्लॉक का उपयोग नहीं कर सकते हैं, क्योंकि आपको लगता है कि डू-ब्लॉक को डी-शर्करा क्यों मिलता है? (रैंपियन के समाधान में भी कहा गया है।) – ivanm

+0

डी ओह, अच्छी कॉल। मुझे अब एक हास्केल प्रोग्रामर की तरह और सोचना चाहिए, क्योंकि मैंने अभी ओपी का कोड लिया है, इसे टाइप-चेक और संकलित किए जाने तक संशोधित किया है, और कहा, "हाँ, यह सही होना चाहिए।" : पी फिर भी, मुझे लगता है कि ओपी का सवाल कम या ज्यादा था "क्या हास्केल टाइप अनुमान लगाता है?" हालांकि उन्होंने इसे इस तरह से नहीं पूछा था। और मेरा मुख्य बिंदु था, हाँ, यह करता है। – MatrixFrog

7

मुख्य मुद्दा यह है कि >>= की आपकी परिभाषा परिपत्र है।

हास्केल के

m >>= f = 
    m >>= \var -> 
    return $ f var 

तो तुम m >>= fm >>= \... के रूप में है, जो परिपत्र है तय कर रहे हैं करने के लिए वाक्य रचना >>= और >> की श्रृंखला के लिए syntatic चीनी है

m >>= f = do 
    var <- m 
    return $ f var   

Desugars करते हैं, तो अपनी परिभाषा।

>>= के साथ आपको क्या करना है, यह परिभाषित करता है कि एम से मान को निकालने के लिए f पर कैसे निकालें। इसके अतिरिक्त, आपके f को एक monadic value वापस करना चाहिए, इसलिए return का उपयोग करना गलत है (यह fmap को परिभाषित करने के तरीके के करीब है)।

Something के लिए >>= की एक परिभाषा हो सकता है:

(Something a) >>= f = f a 

यह पहचान इकाई है - इसके बारे में लिखा एक अच्छा सौदा है - यह कैसे monads काम समझने के लिए एक अच्छी शुरुआत है।

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

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