2011-11-10 11 views
7

मेरे पास एक सामान्य प्रश्न और एक और विशिष्ट मामला प्रश्न है।मोनैड का मिश्रण (आईनेमरेबल और शायद एक उदाहरण के रूप में)

आम तौर पर एक अलग मोनैड कैसे जोड़ता है? क्या मोनड ऑपरेटर के कुछ संयोजन आसान संरचना की अनुमति देते हैं? या क्या किसी को मोनैड की प्रत्येक संभावित जोड़ी को गठबंधन करने के लिए विज्ञापन-प्रक्रिया पद्धतियां लिखनी पड़ती हैं?

एक विशिष्ट उदाहरण के रूप में, मैंने शायद एक मोनड लिखा था। IEnumerable<IMaybe<T>> का उपयोग करने के बारे में कोई कैसे होगा? LINQ एक्सटेंशन (जैसे: if(maybe.HasValue) ... select खंडों के भीतर मैन्युअल रूप से शायद मोनैड में खोदने के अलावा), क्या उनके संबंधित बाइंड इत्यादि के साथ दोनों को संयोजित करने का "monadic" तरीका है?

अन्यथा, अगर मुझे विशिष्ट संयोजन विधियों को लिखना है, तो क्या इस बारे में कुछ सही तरीका है?

public static IEnumerable<B> SelectMany<A, B>(this IEnumerable<A> sequence, Func<A, IMaybe<B>> func) 
    { 
     return from item in sequence 
       let result = func(item) 
       where result.HasValue 
       select result.Value; 
    } 


    public static IEnumerable<C> SelectMany<A, B, C>(this IEnumerable<A> sequence, Func<A, IMaybe<B>> func, Func<A, B, C> selector) 
    { 
     return from item in sequence 
       let value = item 
       let maybe = func(item) 
       where maybe.HasValue 
       select selector(value, maybe.Value); 
    } 
+0

मुझे मोनैड के संयोजन का वास्तव में एक दिलचस्प संदर्भ मिला: http://heinrichapfelmus.github.com/operational/Documentation.html#alternatives-to-monad-transformers यह मोनाड्स के संयोजन के एक सामान्य तरीके की वकालत करता है। आपको यह पेपर भी पढ़ना चाहिए, यह वर्णन करता है कि कैसे डेटा प्रकारों को सामान्य और एक्स्टेंसिबल तरीके से जोड़ना है: http://www.cs.ru.nl/~wouters/Publications/DataTypesALaCarte.pdf –

उत्तर

-1

इस विशिष्ट मामले में, आप MayBe<T> में IEnumerable<T> को लागू कर सकता है, तो यह या तो रिटर्न 0 या 1 मूल्य।

1

शानदार सवाल!

मोनैड ट्रांसफार्मर एक प्रकार है जो मोनैड-नेस को संरक्षित करते समय मनमाने ढंग से आधार मोनैड में कुछ कार्यक्षमता जोड़ता है। अफसोस की बात है, मोनड ट्रांसफार्मर सी # में अप्रचलित हैं क्योंकि वे उच्च प्रकार के प्रकारों का आवश्यक उपयोग करते हैं। तो, हास्केल में काम करना,

class MonadTrans (t :: (* -> *) -> (* -> *)) where 
    lift :: Monad m => m a -> t m a 
    transform :: Monad m :- Monad (t m) 

चलो लाइन के अनुसार इस लाइन पर जाएं। पहली पंक्ति घोषित करती है कि एक मोनड ट्रांसफॉर्मर एक प्रकार t है, जो कि * -> * (यानी, एक तर्क की अपेक्षा रखने वाला एक प्रकार) का तर्क लेता है और इसे किसी अन्य प्रकार के * -> * में बदल देता है। जब आपको एहसास होता है कि सभी मोनैड्स में * -> * है तो आप देख सकते हैं कि इरादा यह है कि t मोनैड अन्य मोनैड में बदल जाता है।

अगली पंक्ति कहना है कि सभी इकाई ट्रांसफार्मर एक lift ऑपरेशन है, जो एक मनमाना इकाई m और लिफ्टों यह ट्रांसफार्मर की दुनिया में ले जाता है t m समर्थन करना चाहिए।

अंत में, transform विधि कहती है कि किसी भी monad m, t m भी एक मोनड होना चाहिए। मैं प्रक्षेपण ऑपरेटर :-the constraints package से उपयोग कर रहा हूं।


यह एक उदाहरण के साथ और अधिक समझ में आ जाएगा। यहां एक मोनैड ट्रांसफार्मर है जो Maybe जोड़ता है-एक मनमानी आधार मोनैड m पर। nothing ऑपरेटर हमें गणना को निरस्त करने की अनुमति देता है।

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) } 

nothing :: Monad m => MaybeT m a 
nothing = MaybeT (return Nothing) 

आदेश में MaybeT के लिए एक इकाई के ट्रांसफार्मर होने के लिए, यह एक इकाई जब भी अपने तर्क एक इकाई है होना चाहिए।

instance Monad m => Monad (MaybeT m) where 
    return = MaybeT . return . Just 
    MaybeT m >>= f = MaybeT $ m >>= maybe (return Nothing) (runMaybeT . f) 

अब MonadTrans कार्यान्वयन लिखने के लिए। lift के कार्यान्वयन को Just में आधार मोनैड के वापसी मूल्य को लपेटता है। का कार्यान्वयन अनिच्छुक है; यह केवल जीएचसी के बाधा सॉल्वर को यह सत्यापित करने के लिए बताता है कि MaybeT वास्तव में जब भी इसका तर्क होता है तो एक मोनड होता है।

instance MonadTrans MaybeT where 
    lift = MaybeT . fmap Just 
    transform = Sub Dict 

अब हम एक monadic गणना जो MaybeT का उपयोग करता है करने के लिए विफलता को जोड़ने के लिए, उदाहरण के लिए, State इकाई लिख सकते हैं। lift हमें मानक State विधियों get और put का उपयोग करने की अनुमति देता है, लेकिन अगर हमें गणना में विफल होने की आवश्यकता है तो हमारे पास nothing तक पहुंच भी है। (मैं IEnumerable (उर्फ [] के अपने उदाहरण का उपयोग के बारे में सोचा है), लेकिन वहाँ कुछ एक इकाई जो पहले से ही इसका समर्थन करता है करने के लिए विफलता जोड़ने के बारे में विकृत है।)

example :: MaybeT (State Int)() 
example = do 
    x <- lift get 
    if x < 0 
    then nothing 
    else lift $ put (x - 1) 

क्या इकाई ट्रांसफार्मर वास्तव में उपयोगी बनाता है उनके stackability है। यह आपको एक क्षमता के साथ बहुत सारे मोनैडों में से कई क्षमताओं के साथ बड़े मोनैड लिखने की अनुमति देता है। उदाहरण के लिए, किसी दिए गए एप्लिकेशन को आईओ करने, कॉन्फ़िगरेशन चर पढ़ने और अपवाद फेंकने की आवश्यकता हो सकती है; इस तरह

type Application = ExceptT AppError (ReaderT AppConfig IO) 

एक प्रकार से एन्कोड किया जाएगा वहाँ the mtl package में उपकरण जो किसी दिए गए ढेर में सटीक संग्रह और इकाई ट्रांसफॉर्मर के आदेश से अधिक सार करने में मदद, आप lift के लिए कॉल छिपाना करने की इजाजत दी है।

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