monads
एक भिक्षु के होते हैं
एक एंडोफूनर । हमारे सॉफ्टवेयर इंजीनियरिंग की दुनिया में, हम कह सकते हैं कि यह एक एकल, अप्रतिबंधित प्रकार के पैरामीटर के साथ डेटाटाइप से मेल खाती है। C # में, यह फ़ॉर्म का कुछ होगा:
class M<T> { ... }
उस डेटाटाइप पर परिभाषित दो ऑपरेशन:
return
/ pure
एक "शुद्ध" मान (यानी, एक T
मान) लेता है और इसे मोनाड में लपेटता है (यानी, यह एक M<T>
मूल्य पैदा करता है )। चूंकि return
C # में एक आरक्षित कीवर्ड है, मैं pure
अब से इस ऑपरेशन को संदर्भित करने के लिए उपयोग करूंगा । C # में, pure
हस्ताक्षर के साथ एक विधि होगी:
M<T> pure(T v);
bind
/ flatmap
एक मानद मूल्य ( M<A>
) और एक फ़ंक्शन लेता है f
। f
एक शुद्ध मूल्य लेता है और एक मुद्रीकृत मूल्य ( M<B>
) लौटाता है । इनसे, bind
एक नया मानद मूल्य ( M<B>
) पैदा करता है । bind
निम्नलिखित C # हस्ताक्षर है:
M<B> bind(M<A> mv, Func<A, M<B>> f);
इसके अलावा, एक मोनाड होने के लिए, pure
और bind
तीन मोनाद कानूनों का पालन करना आवश्यक है।
अब, C # में एक मॉडल बनाने का एक तरीका इंटरफ़ेस का निर्माण करना होगा:
interface Monad<M> {
M<T> pure(T v);
M<B> bind(M<A> mv, Func<A, M<B>> f);
}
(नोट: चीजों को संक्षिप्त और अभिव्यंजक रखने के लिए, मैं इस उत्तर के दौरान कोड के साथ कुछ स्वतंत्रता ले जाऊंगा।)
अब हम ठोस डेटाटाइप्स के लिए मोनोएड को लागू कर सकते हैं Monad<M>
। उदाहरण के लिए, हम निम्नलिखित के लिए निम्नलिखित को लागू कर सकते हैं IEnumerable
:
class IEnumerableM implements Monad<IEnumerable> {
IEnumerable<T> pure(T v) {
return (new List<T>(){v}).AsReadOnly();
}
IEnumerable<B> bind(IEnumerable<A> mv, Func<A, IEnumerable<B>> f) {
;; equivalent to mv.SelectMany(f)
return (from a in mv
from b in f(a)
select b);
}
}
(मैं LINQ सिंटैक्स और मोनडेस के बीच संबंध को कॉल करने के लिए LINQ सिंटैक्स का उपयोग करता हूं। लेकिन ध्यान दें कि हम LINQ क्वेरी को कॉल के साथ बदल सकते हैं SelectMany
।)
अब, क्या हम एक सन्यासी को परिभाषित कर सकते हैं IObservable
? ऐसा लगता है:
class IObservableM implements Monad<IObservable> {
IObservable<T> pure(T v){
Observable.Return(v);
}
IObservable<B> bind(IObservable<A> mv, Func<A, IObservable<B>> f){
mv.SelectMany(f);
}
}
यह सुनिश्चित करने के लिए कि हमारे पास एक मोनाड है, हमें मोनाद कानूनों को साबित करने की आवश्यकता है। यह गैर-तुच्छ हो सकता है (और मैं Rx.NET के साथ पर्याप्त रूप से परिचित नहीं हूं यह जानने के लिए कि क्या उन्हें अकेले विनिर्देश से भी साबित किया जा सकता है), लेकिन यह एक आशाजनक शुरुआत है। इस चर्चा के शेष भाग को सुविधाजनक बनाने के लिए, आइए मान लेते हैं कि इस मामले में मोनाड कानूनों की पकड़ है।
नि: शुल्क मोनाडेस
कोई विलक्षण "मुक्त मोनाड" नहीं है। बल्कि, मुफ्त मोनाड एक वर्ग के भिक्षु हैं जो कि फंक्शनलर्स से निर्मित होते हैं। यही कारण है कि, एक फ़नकार दिया जाता है F
, हम स्वचालित रूप से F
(यानी, मुक्त मोनाद F
) के लिए एक मोदक प्राप्त कर सकते हैं ।
functors
मोनाड्स की तरह, फंक्शनलर्स को निम्नलिखित तीन वस्तुओं द्वारा परिभाषित किया जा सकता है:
- एक डेटाटाइप, एक एकल, अप्रतिबंधित प्रकार चर पर पैरामीटरित।
दो ऑपरेशन:
pure
फ़्यूचर में एक शुद्ध मूल्य लपेटता है। यह pure
एक सन्यासी के लिए अनुरूप है । वास्तव में, फंक्शनलर्स के लिए जो एक मोनड भी हैं, दोनों समान होने चाहिए।
fmap
किसी दिए गए फ़ंक्शन के माध्यम से आउटपुट में नए मूल्यों के लिए मानचित्र मान। यह हस्ताक्षर है:
F<B> fmap(Func<A, B> f, F<A> fv)
मठों की तरह, फंक्शंस कानूनों का पालन करने के लिए फंक्शनलर्स की आवश्यकता होती है।
मोनाड्स के समान, हम निम्नलिखित इंटरफ़ेस के माध्यम से फंक्शनल मॉडल कर सकते हैं:
interface Functor<F> {
F<T> pure(T v);
F<B> fmap(Func<A, B> f, F<A> fv);
}
अब, चूँकि मोनाड फंक्शंस के उप-वर्ग हैं, इसलिए हम Monad
थोड़ा भी रिफ्लेक्टर कर सकते हैं :
interface Monad<M> extends Functor<M> {
M<T> join(M<M<T>> mmv) {
Func<T, T> identity = (x => x);
return mmv.bind(x => x); // identity function
}
M<B> bind(M<A> mv, Func<A, M<B>> f) {
join(fmap(f, mv));
}
}
यहां मैंने एक अतिरिक्त विधि जोड़ी है join
, और दोनों का डिफ़ॉल्ट कार्यान्वयन प्रदान किया है join
और bind
। ध्यान दें, हालांकि, ये परिपत्र परिभाषाएं हैं। इसलिए आपको कम से कम एक या दूसरे को ओवरराइड करना होगा। इसके अलावा, ध्यान दें कि pure
अब से विरासत में मिला है Functor
।
IObservable
और मुफ्त मोनाड्स
अब, क्योंकि हमने एक सन्यासी को परिभाषित किया है IObservable
और चूँकि भिक्षुओं के उप-वर्ग हैं, तो यह इस प्रकार है कि हमें एक फ़नकार के उदाहरण को परिभाषित करने में सक्षम होना चाहिए IObservable
। यहाँ एक परिभाषा है:
class IObservableF implements Functor<IObservable> {
IObservable<T> pure(T v) {
return Observable.Return(v);
}
IObservable<B> fmap(Func<A, B> f, IObservable<A> fv){
return fv.Select(f);
}
}
अब जब हमारे पास एक फ़ंक्टर है जिसे IObservable
हम परिभाषित कर सकते हैं, हम उस फ़नकार से एक मुफ्त मोनाड का निर्माण कर सकते हैं। और यह ठीक है कि कैसे IObservable
मुक्त भिक्षुओं से संबंधित है - अर्थात्, हम से एक मुक्त मठ का निर्माण कर सकते हैं IObservable
।
Cont
मैंने देखा है कि केवल एक ही मोनाड है जिसे मुक्त मोनाद के माध्यम से व्यक्त नहीं किया जा सकता है, कोई संभवतः मान सकता है कि एफआरपी हो सकता है। जैसा कि लगभग कुछ भी हो सकता है ।