monads
एक भिक्षु के होते हैं
एक एंडोफूनर । हमारे सॉफ्टवेयर इंजीनियरिंग की दुनिया में, हम कह सकते हैं कि यह एक एकल, अप्रतिबंधित प्रकार के पैरामीटर के साथ डेटाटाइप से मेल खाती है। C # में, यह फ़ॉर्म का कुछ होगा:
class M<T> { ... }
उस डेटाटाइप पर परिभाषित दो ऑपरेशन:
return/ pureएक "शुद्ध" मान (यानी, एक Tमान) लेता है और इसे मोनाड में लपेटता है (यानी, यह एक M<T>मूल्य पैदा करता है )। चूंकि returnC # में एक आरक्षित कीवर्ड है, मैं 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मैंने देखा है कि केवल एक ही मोनाड है जिसे मुक्त मोनाद के माध्यम से व्यक्त नहीं किया जा सकता है, कोई संभवतः मान सकता है कि एफआरपी हो सकता है। जैसा कि लगभग कुछ भी हो सकता है ।