موناد (مفهوم برمجي)

في البرمجة الوظيفية، تُستخدم المونادات لتنظيم العمليات الحسابية كسلسلة من الخطوات، حيث تنتج كل خطوة قيمة بالإضافة إلى معلومات إضافية عن الحساب، مثل احتمالية الفشل، أو عدم الحتمية، أو الأثر الجانبي. بشكل أكثر رسمية، تُعرف المونادة بأنها باني نوع M مزود بعمليتين،  لرفع قيمة إلى السياق المونادي، و لربط العمليات المونادية. ببساطة، يمكن اعتبار المونادات على أنها واجهة مُطبقة على بُناة الأنواع، مما يسمح للدوال بالتعامل مع أنواع مختلفة من بُناة الأنواع التي تنفذ مفهوم المونادة (مثل ، و، وغيرها).

يعود كل من مفهوم المونادة والمصطلح ذاته إلى نظرية الفئات، حيث تُعرف المونادة بأنها دالة ذات بنية إضافية. أظهرت الأبحاث التي بدأت في أواخر الثمانينيات وأوائل التسعينيات أن المونادات يمكنها توحيد نماذج وظيفية لمشكلات حوسبية كانت تبدو متباينة. كما تقدم نظرية الفئات عددًا من المتطلبات الشكلية، المعروفة باسم قوانين المونادة، والتي يجب أن تفي بها أي مونادة ويمكن استخدامها للتحقق الشكلي من صحة الشيفرة المونادية.

نظرًا لأن المونادات تُظهر الدلالة الشكلية لنوع معين من الحسابات، فيمكن استخدامها أيضًا لتنفيذ ميزات لغوية مريحة. بعض اللغات، مثل هاسكل، توفر تعريفات جاهزة ضمن مكتبة برمجية أساسية لبنية المونادة العامة والتطبيقات الشائعة لها.

 نظرة عامة 
"بالنسبة لمونادة m، فإن القيمة من النوع m a تمثل الوصول إلى قيمة من النوع a ضمن سياق المونادة." — سي. إيه. ماكانإجابة C. A. McCann (23 يوليو 2010): كيف ولماذا تعمل مونادة Cont في هاسكل؟ 

بشكل أدق، يمكن استخدام المونادة عندما لا يكون الوصول غير المقيَّد إلى قيمة ما مناسبًا لأسباب تتعلق بالسيناريو المحدد. في حالة مونادة مايبي، يعود السبب إلى أن القيمة قد لا تكون موجودة. وفي حالة مونادة IO، يعود السبب إلى أن القيمة قد لا تكون معروفة بعد، كما هو الحال عندما تمثل المونادة إدخال المستخدم الذي لن يتم توفيره إلا بعد عرض موجه. في جميع الحالات، يتم التقاط السيناريوهات التي يكون فيها الوصول منطقيًا من خلال عملية الربط المعرفة لتلك المونادة؛ فبالنسبة لمونادة مايبي، لا يتم ربط القيمة إلا إذا كانت موجودة، وبالنسبة لمونادة IO، لا يتم ربط القيمة إلا بعد تنفيذ العمليات السابقة في التسلسل.

يمكن إنشاء مونادة من خلال تعريف باني نوع M وعمليتين:

 return :: a -> M a (وغالبًا ما تُسمى أيضًا وحدة)، والتي تستقبل قيمة من النوع a وتغلفها داخل "قيمة مونادية" من النوع M a، و
 bind :: (M a) -> (a -> M b) -> (M b) (ويُمثَّل عادةً بالرمز >>=)، والتي تستقبل قيمة مونادية من النوع M a ودالة f تأخذ قيمًا من النوع الأساسي a. تقوم bind بفك القيمة a، وتُطبق f عليها، وتعالج ناتج f كقيمة مونادية M b.

(هناك بناء بديل لكنه مكافئ يستخدم دالة join بدلًا من عامل bind، يمكن العثور عليه في القسم لاحقًا تحت عنوان .)

باستخدام هذه العناصر، يمكن للمبرمج إنشاء سلسلة من استدعاءات الدوال (أو "أنبوب معالجة") تربط معًا باستخدام عامل bind، حيث تُحوِّل كل دالة مدخلاتها من النوع العادي، ويتولى عامل bind التعامل مع القيمة المونادية الناتجة، ويمررها إلى الخطوة التالية في التسلسل.

عادةً، قد يحتوي عامل الربط >>= على كود خاص بالمونادة يؤدي خطوات حسابية إضافية لا تتوفر داخل الدالة المُمررة كوسيط. بين كل زوج من استدعاءات الدوال المرتبطة، يمكن لـ bind إدخال معلومات إضافية في القيمة المونادية m a، وهي معلومات لا تكون متاحة داخل الدالة f، وتمريرها عبر سلسلة المعالجة. كما يمكنها أيضًا التحكم بدقة أكبر في تدفق التنفيذ، مثل استدعاء الدالة فقط في ظل ظروف معينة، أو تنفيذ الاستدعاءات بترتيب معين.

 مثال: مونادة مايبي 

أحد الأمثلة على المونادات هو النوع ربما أو مايبي Maybe. فالقيم غير المعروفة هي إحدى المشكلات التي لا توفر العديد من لغات البرمجة الإجرائية أدوات محددة للتعامل معها، مما يتطلب استخدام نمط الكائن الفارغ  أو التحقق من القيم غير الصالحة عند كل عملية للتعامل مع القيم غير المعرفة. هذا يسبب أخطاء ويصعّب بناء برامج قوية تتعامل مع الأخطاء بسلاسة. النوع Maybe يجبر المبرمج على التعامل مع هذه النتائج غير المعرفة من خلال تحديد حالتين صريحتين للنتيجة: Just ⌑النتيجة⌑، أو Nothing. على سبيل المثال، قد يكون المبرمج بصدد بناء محلل يعيد نتيجة وسيطة، أو يشير إلى حالة يجب على المبرمج التعامل معها أيضاً. بقليل من الأدوات الدالية الإضافية، يتحول النوع Maybe إلى موناد متكامل الميزات.

في معظم اللغات، يُعرف موناد مايبي أيضاً بنوع الخيار ، وهو نوع يشير إلى ما إذا كانت القيمة موجودة أم لا. وعادةً ما يُعبّر عنه كنوع مُعَدَّد. في لغة الرست، يُعرف باسم Option<T> ويمكن أن يحتوي على قيمة من النوع العام برمجة عامة T، أو على المتغير الفارغ: None.

// <T> يمثل نوعًا عامًا
enum Option<T> {
    Some(T),
    None,
}

يمكن أيضًا اعتبار Option<T> كنوع "غلاف"، وهنا يأتي ارتباطه بالمونادات. في اللغات التي تحتوي على نوع مايبي، توجد دوال تساعد على استخدامه مثل تركيب دوال مونادية مع بعضها البعض، واختبار ما إذا كانت المايبي تحتوي على قيمة.

في المثال التالي، نستخدم مايبي كنتيجة لدوال قد تفشل، مثل حالة القسمة على صفر:

fn divide(x: Decimal, y: Decimal) -> Option<Decimal> {
    if y == 0 { return None }
    else { return Some(x / y) }
}
// divide(1.0, 4.0) -> يعيد Some(0.25)
// divide(3.0, 0.0) -> يعيد None

طريقة لاختبار ما إذا كانت مايبي تحتوي على قيمة هي استخدام عبارات if:

let m_x = divide(3.14, 0.0);
if let Some(x) = m_x {
    println!("الإجابة: {}", x)
} else {
    println!("فشل القسمة، خطأ قسمة على صفر...")
}

بعض اللغات تدعم مطابقة النمط:

let result = divide(3.0, 2.0);
match result {
    Some(x) => println!("الإجابة: {}", x),
    None => println!("فشلت القسمة؛ المحاولة القادمة ستكون أفضل."),
}

يمكن للمونادات أن تُركّب دوال تُعيد مايبي، وأن تُجمِّعها معًا. مثال عملي: دالة تستقبل قيمًا من النوع مايبي وتُرجِع قيمة مايبي واحدة تكون لا شيء إذا كانت أي من القيم المُدخَلة هي لا شيء (Nothing).

fn chainable_division(maybe_x: Option<Decimal>, maybe_y: Option<Decimal>) -> Option<Decimal> {
    match (maybe_x, maybe_y) {
        (Some(x), Some(y)) => {
            if y == 0 { return None }
            else { return Some(x / y) }
        },
        _ => return None
    }
}
chainable_division(chainable_division(Some(2.0), Some(0.0)), Some(1.0));

بدلاً من تكرار تعبيرات Some، يمكن استخدام عامل يُعرف بـ "bind" (أو "map"، "flatmap"، أو "shove"):

let maybe_x: Option<Decimal> = Some(1.0);
let maybe_result = maybe_x.map(add_one).map(decimal_to_string);

في Haskell، يوجد عامل "bind" (>>=) لكتابة ذلك بشكل أنيق شبيه بـ تركيب الدوال:

halve :: Int -> Maybe Int
halve x
  | even x = Just (x `div` 2)
  | odd x  = Nothing
halve x >>= halve 

يمكن أيضًا تبسيط chainable_division باستخدام دالة مجهولة (lambda):

chainable_division(mx, my) = 
    mx >>= (\x -> my >>= (\y -> Just (x / y)))

بالتالي، هذه هي الشروط اللازمة لتشكيل موناد:

النوع المونادي
مثل Maybe 
عملية الوحدة
محول النوع مثل Just(x) 
عملية الربط
تجميع دوال مونادية مثل >>= أو .flatMap() 

كل المونادات تحتوي على هذه المكونات الثلاثة الأساسية، وقد تختلف في خواص إضافية، لكنها تشترك في هذه القاعدة.

 التعريف 
التعريف الأكثر شيوعًا للموناد في البرمجة الدالية، كما استُخدم في المثال أعلاه، يستند في الواقع إلى  ⟨T، η، μ⟩ بدلاً من التعريف القياسي في نظرية الفئات. ومع ذلك، فإن البنيتين متكافئتان رياضيًا، لذا فإن أي تعريف منهما يُنتج مونادًا صالحًا. عند توفر نوعين أساسيين معرفين جيدًا  و، فإن الموناد يتكوّن من ثلاثة أجزاء:
 منشئ نوع  يُكوّن نوعًا موناديًا 
 التحويل في c++, ويُطلق عليه غالبًا unit أو return، ويضمّن كائنًا  داخل الموناد:  
  توليف، يُطلق عليه عادةً bind (كما في المتغير الحر والمتغير المقيد) ويُرمز له عادةً بالرمز تدوين وسطي >>= أو بطريقة تُدعى flatMap، يفك تغليف متغيّر مونادي ثم يُدخله في دالة/تعبير مونادي، منتجًا قيمة مونادية جديدة:  


لكي يُعد البناء مونادًا كاملًا، يجب أن تحترم هذه الأجزاء الثلاثة عددًا من القوانين:  
  هو عنصر محايد لـ:  
  هو أيضًا عنصر محايد أيمن لـ:  
  هو عملية تجميعية من حيث الأساس:  

جبرِيًا، هذا يعني أن أي موناد يُنتج فئة (تُسمى فئة كلايسلي) و وحدية في فئة المؤثرات (من القيم إلى الحسابات)، حيث يكون التركيب المونادي هو العامل الثنائي في وحدانية، و هو العنصر المحايد في هذه الوحدانية.

 الاستخدام 
تتجاوز قيمة نمط الموناد مجرد تكثيف الشيفرة وتوفير رابط إلى التفكير الرياضي.  
بغض النظر عن اللغة أو نمط برمجة الافتراضي الذي يستخدمه المطور، فإن اتباع نمط الموناد يجلب العديد من فوائد البرمجة الدالية البحتة.  
عن طريق تجسيد نوع معين من العمليات الحسابية، لا يقوم الموناد فقط بالتغليف التفاصيل المملة لهذا النمط من العمليات، بل يفعل ذلك بأسلوب برمجة تصريحية، مما يُحسّن من وضوح الشيفرة.  
نظرًا لأن القيم المونادية تمثّل بشكل صريح ليس فقط القيم المحسوبة، بل أيضًا الآثار المحسوبة، يمكن استبدال التعبير المونادي بقيمته وفق مبدأ شفافية مرجعية، تمامًا كما هو الحال مع التعبيرات البحتة، مما يسمح بالعديد من التقنيات والتحسينات القائمة على إعادة الكتابة.

عادةً ما يستخدم المبرمجون  لربط الدوال المونادية في تسلسل، مما دفع البعض إلى وصف المونادات بأنها "فواصل منقوطة قابلة للبرمجة"، في إشارة إلى الطريقة التي تستخدم بها العديد من لغات برمجة أمرية الفواصل المنقوطة للفصل بين العبارات.  
ومع ذلك، فإن المونادات لا تقوم فعليًا بترتيب العمليات الحسابية؛ حتى في اللغات التي تُستخدم فيها كميزة أساسية، يمكن لتركيب الدوال الأبسط ترتيب الخطوات داخل البرنامج.  
تتمثل الفائدة العامة للموناد في تبسيط بنية البرنامج وتحسين فصل الاهتمامات من خلال التجريد.

يمكن أيضًا رؤية بنية الموناد كنسخة رياضية فريدة ووقت التصريف من نموذج التصميم ديكور.  
بعض المونادات يمكنها تمرير بيانات إضافية غير متاحة للدوال، وبعضها يُمارس تحكمًا أدق في التنفيذ، كأن يستدعي دالة فقط في ظروف معينة.  
ونظرًا لأنها تتيح لمبرمجي التطبيقات تنفيذ منطق العمل مع تحميل الشيفرة المتكررة على وحدات مطورة مسبقًا، يمكن اعتبار المونادات أداة لبرمجة موجهة بالسمات.

ومن الاستخدامات المهمة الأخرى للمونادات عزل الآثار الجانبية، مثل وحدات الإدخال والإخراج أو حالة قابلة للتغيير، في الشيفرة البحتة.  
حتى اللغات الدالية البحتة تستطيع تنفيذ هذه العمليات "غير البحتة" بدون استخدام المونادات، وذلك عبر مزيج معقد من تركيب الدوال والاستمرارية على وجه الخصوص.  
لكن باستخدام المونادات، يمكن تجريد الكثير من هذا الهيكل، وذلك عن طريق أخذ كل نمط متكرر في شيفرة CPS وتجميعه في موناد مميز.

إذا لم تكن اللغة تدعم المونادات بشكل افتراضي، فإنه لا يزال من الممكن تنفيذ النمط، وغالبًا دون صعوبة كبيرة.  
عند ترجمة بنية الموناد من نظرية الفئات إلى مصطلحات برمجية، تكون مفهومًا عامًا يمكن تعريفه مباشرةً في أي لغة تدعم ميزة مكافئة لتعدد الأشكال المقيد.  
قدرة المفهوم على البقاء غير مرتبط بالتفاصيل التشغيلية أثناء العمل على أنواع أساسية هي ميزة قوية، لكن الخصائص الفريدة والسلوك الصارم للمونادات يميزها عن المفاهيم الأخرى.

 التطبيقات 
تركز مناقشات المونادات المحددة عادةً على حل مشكلة تنفيذ ضيقة النطاق، إذ إن كل موناد يمثل شكلًا حسابيًا معينًا.  
ومع ذلك، في بعض الحالات، يمكن للتطبيق أن يحقق أهدافه العامة من خلال استخدام المونادات المناسبة ضمن منطق العمل الأساسي له.

فيما يلي بعض التطبيقات التي تتخذ من المونادات جوهرًا لتصميمها:
 تستخدم مكتبة المحلل النحوي بارسك المونادات لدمج قواعد التجزئة بسيطة في قواعد أكثر تعقيدًا، وهي مفيدة بشكل خاص لـلغة مخصصة النطاق الصغيرة.
 إكس موناد هو مدير نوافذ مبلط يتمحور حول بنية بيانات "زيبر"، والتي يمكن معالجتها كموناد في حالة خاصة من الاستمرارية المحددة.
 يوفر الاستعلام التكميلي اللغوي من مايكروسوفت لغة استعلام لإطار دوت نت فريموورك، وهو مستوحى بشكل كبير من مفاهيم البرمجة الدالية، بما في ذلك عوامل أساسية لتركيب الاستعلامات باستخدام المونادات.
 زيبر إف  سي هو نظام ملفات بسيط وتجريبي، يستخدم أيضًا بنية "زيبر" بشكل أساسي لتنفيذ ميزاته.
 يوفر إطار الامتدادات التفاعلية في جوهره واجهة (مونادية أو مزدوجة الموناد) للتعامل مع الجريان، ويُجسّد بذلك نمط المراقب.

 التاريخ 
يعود استخدام مصطلح "موناد" في البرمجة إلى لغات البرمجة إيه بي إل وجيه، وهما تميلان إلى كونها وظيفية بحتة. ومع ذلك، فإن "الموناد" في هذه اللغات ليست سوى اختصار لدالة تأخذ مُعاملاً واحداً (بينما تُسمّى الدالة التي تأخذ معاملين "دياد"، وهكذا).

كان عالم الرياضيات روجيه غوديمان أول من صاغ مفهوم الموناد (وسمّاه "البناء القياسي") في أواخر خمسينيات القرن العشرين، إلا أن المصطلح "موناد" الذي أصبح شائعاً لاحقاً نُشر بفضل عالم نظرية الفئات سوندرز ماكلين. ومع ذلك، فإن الصيغة المعرّفة أعلاه باستخدام ، وُصفت أصلاً سنة 1965 بواسطة عالم الرياضيات هاينريش كلايسلي لإثبات أن أي موناد يمكن تمييزها على أنها اقتران بين دالتين متحدتي التغاير.

بدءًا من ثمانينيات القرن العشرين، بدأ مفهوم نمط الموناد يظهر تدريجياً في مجتمع علوم الحاسوب. ووفقاً لباحث لغات البرمجة فيليب وادلر، فإن عالم الحاسوب جون س. رينولدز كان قد تنبأ بعدة جوانب من هذا المفهوم في سبعينيات وأوائل ثمانينيات القرن العشرين، عندما ناقش قيمة الاستمرارية، ونظرية الفئات كمصدر غني للدلالات الرسمية، والتمييز النمطي بين القيم والعمليات الحسابية.

كما أن لغة البحث أوبال، التي استمر تطويرها حتى عام 1990، اعتمدت فعلياً إدخال/إخراج مبني على نوع مونادي، لكن العلاقة لم تُدرك في حينها.

كان عالم الحاسوب أوجينيو موجي أول من ربط صراحة بين الموناد في نظرية الفئات والبرمجة الوظيفية، في ورقة مؤتمر عام 1989، تلتها ورقة أكثر تطوراً في مجلة علمية سنة 1991. في أعمال سابقة، كان عدد من علماء الحاسوب قد قدموا نظرية الفئات كوسيلة لتوفير دلالات للتكامل اللامبداوي. أما البصيرة الرئيسية لدى موجي فكانت أن البرنامج الحقيقي في العالم الواقعي ليس مجرد دالة من القيم إلى قيم أخرى، بل هو تحويل يُشكّل "عمليات حسابية" على تلك القيم. وعند صياغته من منظور نظرية الفئات، يتبيّن أن المونادات هي البنية المناسبة لتمثيل هذه العمليات الحسابية.

وقد ساهم آخرون في نشر هذا المفهوم وتوسيعه، منهم فيليب وادلر وسيمون بيتون جونز، وكلاهما كان مشاركاً في تحديد مواصفات لغة هاسكل. على وجه الخصوص، استخدمت هاسكل نموذج "تدفق كسول" إشكالي حتى الإصدار 1.2 للتوفيق بين الإدخال/الإخراج والتقييم الكسول، إلى أن تم التحول إلى واجهة مونادية أكثر مرونة.

استمر مجتمع هاسكل في تطبيق المونادات على العديد من مشكلات البرمجة الوظيفية، وفي عقد 2010، أدرك الباحثون الذين يعملون بهاسكل في نهاية المطاف أن المونادات هي مرافق دالي للتطبيق أيضاً؛Brent Yorgey Typeclassopedia ، وأن المونادات والأسهم كلاهما وحديات.Brent Yorgey Monoids 

في البداية، كانت البرمجة باستخدام المونادات مقتصرة إلى حد كبير على هاسكل وتفرعاتها، لكن مع تأثير البرمجة الوظيفية على أنماط البرمجة الأخرى، تبنت العديد من اللغات نمط الموناد (بروح المفهوم إن لم يكن بالاسم). توجد صيغ له الآن في سكيم، بيرل، بايثون، راكت، كلوجر، سكالا، إف شارب، وقد تم النظر في تضمينه ضمن معيار جديد للغة أم أل.

 التحليل 
إحدى فوائد نمط الموناد هي إدخال دقة رياضية على تركيب العمليات الحسابية. 
فيمكن استخدام قوانين الموناد ليس فقط للتحقق من صحة تطبيق معين، بل يمكن كذلك الاستفادة من الخصائص الموروثة من البُنى ذات الصلة (مثل الدوال المرافقة) من خلال الأنماط الفرعية.

 التحقق من قوانين الموناد 
بالعودة إلى مثال Maybe، فقد تم إعلان مكوناته لتُشكّل موناد، ولكن لم يتم تقديم إثبات على أنها تفي بقوانين الموناد.

يمكن تصحيح ذلك بإدخال تفاصيل Maybe في أحد طرفي القوانين العامة، ثم بناء سلسلة من المساوات الجبرية للوصول إلى الطرف الآخر:

 القانون 1:  eta(a) >>= f(x)  ⇔  (Just a) >>= f(x)  ⇔  f(a)

 القانون 2: ma >>= eta(x) ⇔ ma

        إذا كانت ma هي (Just a) فإن:
            eta(a) ⇔ Just a
        وإلا:
            Nothing ⇔ Nothing
        نهاية الشرط

 القانون 3:  ((ma >>= f(x)) >>= g(y)) ⇔ ma >>= (f(x) >>= g(y))

        إذا كانت (ma >>= f(x)) هي (Just b) فإن:
            g(ma >>= f(x))
        وإلا:
            Nothing
        نهاية الشرط

        ⇔ إذا كانت ma هي (Just a) و f(a) هي (Just b) فإن:
                (g ∘ f) a
            وإلا إذا كانت ma هي (Just a) و f(a) = Nothing فإن:
                Nothing
            وإلا:
                Nothing
        نهاية الشرط

 الاشتقاق من الدوال المرافقة 
على الرغم من ندرة ذلك في علوم الحاسوب، يمكن استخدام نظرية الفئات مباشرة، حيث تُعرّف الموناد على أنها دوال مع تحويلين طبيعيين إضافيين.

للبدء، يتطلب الأمر وجود دالة من الدرجة العليا (أو "وظيفية") تُسمى  لتأهيل البنية لتكون دالة مرافقة:

وهذا ليس دائمًا أمرًا صعبًا، خاصة عند اشتقاق الموناد من دالة مرافقة موجودة مسبقًا، حيث يرث الموناد الدالة  تلقائيًا. (ولأسباب تاريخية، تسمى هذه الدالة fmap في لغة هاسكل.)

التحويل الأول في الموناد هو ذاته  من ثلاثية كلايسلي، ولكن باتباع تسلسل البُنى، يتضح أن  تُميز دالة مرافقة تطبيقية، وهي بنية وسيطة بين الموناد والدالة المرافقة الأساسية. في هذا السياق، يُشار إلى  أحيانًا بـ pure لكنها تبقى نفس الدالة. ما يختلف في هذا البناء هو القانون الذي يجب أن تفي به ؛ فبما أن  غير معرف هنا، فإن القيد يُعطى من خلال  بدلًا منه:

تتمثل القفزة النهائية من الدالة التطبيقية إلى الموناد في التحويل الثاني، وهو دالة join (وفي نظرية التصنيف يُشار إليها غالبًا بالرمز )، والتي "تُسطّح" التطبيقات المتداخلة للموناد:

وبصفتها الدالة المميزة، يجب أن تحقق  أيضًا ثلاث صور من قوانين الموناد:



بغض النظر عمّا إذا كان المبرمج يعرف الموناد بشكل مباشر أو باستخدام ثلاثية كليزلي، فإن البنية الأساسية تظل نفسها، ويمكن اشتقاق الأشكال من بعضها بسهولة:

 مثال آخر: القائمة  

يُظهر موناد القائمة بشكل طبيعي كيف يمكن أن يكون اشتقاق الموناد من دالة تطبيقية أبسط أمرًا مفيدًا.
في العديد من لغات البرمجة، تأتي بنية القائمة معرفة مسبقًا مع بعض الميزات الأساسية، لذا يُفترض هنا أن منشئ النوع List وعامل  (والذي يُكتب بصيغة ++ في الصيغة الترتيبية) متاحان مسبقًا.

إدراج قيمة بسيطة داخل قائمة هو أمر سهل في معظم اللغات:
 unit(x)  =  [x]
من هذه النقطة، قد يبدو أن تطبيق دالة بشكل تكراري باستخدام اشتمال القائمة خيار سهل لـ  وتحويل القوائم إلى موناد كامل.
الصعوبة في هذا النهج هي أن  يتوقع دوالًا مونادية، والتي تُنتج قوائم بحد ذاتها؛
ومع تكرار تطبيق الدوال، تتراكم طبقات من القوائم المتداخلة، مما يتطلب أكثر من مجرد فهم بسيط.

مع ذلك، فإن إجراء تطبيق أي دالة بسيطة على القائمة بأكملها، أي ، هو إجراء مباشر:
 (map φ) xlist  =  [ φ(x1), φ(x2), ..., φ(xn) ]
الآن، هاتان العمليتان ترفّعان بالفعل List إلى دالة تطبيقية.
ولكي تتأهل تمامًا كموناد، يتطلب الأمر فقط تعريفًا صحيحًا لـ  لتسطيح البنية المتكررة، ولكن بالنسبة للقوائم، فهذا يعني فقط إزالة التغليف الخارجي للقائمة ودمج القوائم الداخلية التي تحتوي على القيم:

 join(xlistlist)  =  join([xlist1, xlist2, ..., xlistn])
                  =  xlist1 ++ xlist2 ++ ... ++ xlistn
الموناد الناتج ليس مجرد قائمة، بل قائمة تُعيد تشكيل نفسها تلقائيًا وتُبسط مع تطبيق الدوال.
يمكن الآن اشتقاق  أيضًا باستخدام صيغة فقط، ثم استخدامها لتمرير قيم List خلال سلسلة من الدوال المونادية:
تصغير|upleft=1.4|يسار|يمكن أن يُبسط موناد List استخدام الدوال متعددة القيم، مثل الجذور المركبة.
 (xlist >>= f)  =  join ∘ (map f) xlist
أحد التطبيقات لهذا الموناد القائمي هو تمثيل الحوسبة غير الحتمية.
يمكن لـ List أن تحتفظ بنتائج جميع المسارات التنفيذية في خوارزمية ما، ثم تُبسّط نفسها في كل خطوة لتنسى أي المسارات أدت إلى أي نتائج (وهو اختلاف مهم أحيانًا عن الخوارزميات الحتمية الكاملة).
فائدة أخرى هي أنه يمكن تضمين الفحوصات داخل الموناد؛ إذ يمكن تقليم مسارات محددة بطريقة شفافة عند أول نقطة فشل، دون الحاجة لإعادة كتابة الدوال في سلسلة التنفيذ.

الموقف الثاني الذي يتألق فيه List هو تركيب دالة متعددة القيم.
فعلى سبيل المثال، الجذر الـ لعدد ما يجب أن يُنتج  عددًا مركبًا مميزًا، ولكن إذا تم أخذ الجذر الـ لتلك النتائج، فإن القيم النهائية الـ يجب أن تتطابق مع ناتج الجذر الـ مباشرة.
يقوم List بأتمتة هذه المشكلة بالكامل، مُبسّطًا النتائج من كل خطوة في قائمة مسطحة وصحيحة رياضيًا.

 تقنيات 

توفر المونات تقنيات مثيرة تتجاوز مجرد تنظيم منطق البرامج. يمكن أن تمهد المونات الطريق لميزات تركيبية مفيدة، في حين تتيح طبيعتها الرياضية وعالية المستوى درجة كبيرة من التجريد.

 السكر التركيبي 
على الرغم من أن استخدام  بشكل صريح غالبًا ما يكون منطقيًا، فإن العديد من المبرمجين يفضلون صياغة تشبه التعليمات الإمبراطية (وتُعرف باسم "السكر التركيبي" في هاسكل، و"تدوين الأداء" في اللغة كامل الموضوعية، و"التعبيرات الحسابية" في إف شارب، و"للفهم" في سكالا). هذا مجرد تجميل لغوي يُخفي سلسلة موناتية خلف كتلة شيفرة، ويقوم المترجم لاحقًا بتحويل هذه التعبيرات بهدوء إلى كود وظيفي داخلي.

يمكن إظهار هذه الميزة من خلال تحويل دالة add باستخدام Maybe في هاسكل. الشكل غير الموناتي لـ add في هاسكل يبدو هكذا:
add mx my =
    case mx of
        Nothing -> Nothing
        Just x  -> case my of
                       Nothing -> Nothing
                       Just y  -> Just (x + y)

أما في هاسكل الموناتي، فإن return هو الاسم القياسي لـ ، ويجب التعامل مع تعبيرات لامبدا بشكل صريح، ولكن حتى مع هذه التفاصيل التقنية، فإن مونة Maybe تسمح بتعريف أنظف:
add mx my =
    mx >>= (\x ->
        my >>= (\y ->
            return (x + y)))

ومع استخدام السكر التركيبي، يمكن تبسيط ذلك أكثر إلى تسلسل واضح وسهل القراءة:
add mx my = do
    x <- mx
    y <- my
    return (x + y)

مثال ثانٍ يوضح كيف يمكن استخدام Maybe في لغة مختلفة تمامًا: F#.
باستخدام تعبيرات الحوسبة، يمكن كتابة دالة "قسمة آمنة" تُعيد None عند وجود معامل غير صالح أو قسمة على صفر، كما يلي:
let readNum () =
  let s = Console.ReadLine()
  let succ,v = Int32.TryParse(s)
  if (succ) then Some(v) else None

let secure_div = 
  maybe { 
    let! x = readNum()
    let! y = readNum()
    if (y = 0) 
    then None
    else return (x / y)
  }

وعند وقت البناء، سيقوم المترجم داخليًا "بتفكيك" هذا السكر التركيبي إلى سلسلة أكثر كثافة من استدعاءات :
maybe.Delay(fun () ->
  maybe.Bind(readNum(), fun x ->
    maybe.Bind(readNum(), fun y ->
      if (y=0) then None else maybe.Return(x / y))))

وأخيرًا، حتى قوانين المونات العامة يمكن التعبير عنها باستخدام السكر التركيبي:
do { x <- return v; f x }            ==  do { f v }
do { x <- m; return x }              ==  do { m }
do { y <- do { x <- m; f x }; g y }  ==  do { x <- m; y <- f x; g y }

 الواجهة العامة 

تحتاج كل مونة إلى تنفيذ محدد يستوفي قوانين المونات، ولكن الجوانب الأخرى مثل علاقتها بالبنى الأخرى أو العبارات الاصطلاحية القياسية في اللغة تكون مشتركة بين جميع المونات.  
نتيجة لذلك، قد توفر لغة أو مكتبة برمجية واجهة عامة باسم Monad تتضمن نموذج دالة|نماذج للدوال، وعلاقات التوريث، وحقائق عامة أخرى.  
وبالإضافة إلى توفير بداية جاهزة للتطوير وضمان أن ترث المونة الجديدة خصائص من نوع أعلى (مثل الدوال المرافقة)، فإن التحقق من تصميم المونة مقابل الواجهة العامة يضيف طبقة إضافية من مراقبة الجودة.

 المعاملات 
يمكن غالبًا تبسيط الشيفرة الموناتية بشكل أكبر من خلال الاستخدام الحكيم للمعاملات.  
يُعد الدال  مفيدًا بشكل خاص، لأنه يعمل مع أكثر من مجرد دوال موناتية مخصصة؛ فطالما أن دالة موناتية ينبغي أن تعمل بشكل مماثل لمُعامل معرف مسبقًا، يمكن استخدام  لـ"رفع" هذا المعامل البسيط إلى نظير موناتي مباشرة.  
باستخدام هذه التقنية، يمكن تبسيط تعريف add من مثال Maybe إلى:
add(mx,my)  =  map (+)

ويمكن اتخاذ خطوة أبعد بتعريف add ليس فقط لـMaybe، بل لكل واجهة Monad.  
وبذلك، أي مونة جديدة تطابق الواجهة البنيوية وتنفذ دالة  الخاصة بها سترث تلقائيًا نسخة مرفوعة من add.  
التغيير الوحيد المطلوب للدالة هو تعميم توقيع النوع:
add : (Monad Number, Monad Number) → Monad Number

معامل موناتي آخر مفيد أيضًا في التحليل هو التركيب الموناتي (ويُمثل هنا بالصيغة >=>)، والذي يتيح ربط الدوال الموناتية بأسلوب رياضي أكثر:
(f >=> g)(x)  =  f(x) >>= g

وباستخدام هذا المعامل، يمكن كتابة قوانين المونات بصيغة تعتمد على الدوال فقط، مما يبرز علاقتها بخاصيتي التجميع ووجود العنصر المحايد:
(unit >=> g)     ↔  g  
(f >=> unit)     ↔  f  
(f >=> g) >=> h  ↔  f >=> (g >=> h)

وبالتالي، فإن ما سبق يوضح معنى كتلة "do" في هاسكل:
do  
 _p <- f(x)  
 _q <- g(_p)  
 h(_q)        ↔  (f >=> g >=> h)(x)

 أمثلة إضافية 

 مونايد الهوية 
أبسط أنواع المونايد هو مونايد الهوية، والذي يقوم فقط بوضع تعليقات توضيحية على القيم والدوال العادية ليتوافق مع قوانين المونايد:  
 '''newtype''' Id T  =  T  

 unit(x)    =  x  
 (x >>= f)  =  f(x)
لكن Identity له استخدامات حقيقية، مثل توفير عودية للمحولات المونايدية التكرارية.  
كما يمكن استخدامه أيضًا لتنفيذ تعيين متغيرات أساسية ضمن كتلة بأسلوب برمجة إجرائي.

 المجموعات 
أي مجموعة تملك عملية  صحيحة تُعد مونويدًا بالفعل، لكن يتبين أن List ليست النوع الوحيد من المجموعات التي تملك  معرفًا جيدًا وتُصنف كمونايد.  
بل يمكن تحويل List إلى مجموعات مونايدية أخرى بمجرد فرض خصائص خاصة على :

 نوع المجموعة  خصائص المونويد  خصائص التوافقيات تبادلي؟  إديمبوتنت؟  تفاصيل  مرتب؟  عناصر فريدة؟       مونويد حر     مجموعة متعددة محدودة          مجموعة نهائية         

 مونايد الإدخال/الإخراج (هاسكل)  
كما ذُكر سابقًا، لا يجب أن يحتوي الكود النقي على تأثيرات جانبية غير مُدارة، لكن ذلك لا يمنع البرنامج من وصف وإدارة التأثيرات بشكل صريح.  
هذا المفهوم هو جوهر مونايد هاسكل المسمى IO، حيث يمكن اعتبار الكائن من النوع IO a بمثابة وصف لفعل يُنفذ في العالم، مع إمكانية تقديم معلومات من نوع a.  
العملية التي لا تقدم أي معلومات عن العالم تكون من النوع IO ()، وتُرجع القيمة الوهمية ().  
عند ربط قيمة IO بدالة، تقوم الدالة بحساب الفعل التالي الذي سيتم تنفيذه بناءً على معلومات العالم المقدمة من الفعل السابق (مثل إدخال المستخدم أو ملفات).  

والأهم من ذلك، أن قيمة مونايد IO لا يمكن ربطها إلا بدالة تُرجع مونايد IO آخر، مما يفرض ترتيبًا صارمًا للأفعال، بحيث لا يتم تنفيذ إلا الأفعال المطلوبة، وبالترتيب المحدد.

على سبيل المثال، لدى هاسكل دوال تتعامل مع نظام الملفات، مثل واحدة تتحقق مما إذا كان الملف موجودًا، وأخرى تحذفه:
doesFileExist :: FilePath -> IO Bool
removeFile :: FilePath -> IO ()

الدالة الأولى تهتم بوجود الملف، وتُرجع نوع البيانات المنطقية داخل مونايد IO،  
أما الثانية فتهتم فقط بالفعل (الحذف) لذا تُرجع IO () فارغًا.

ولا يقتصر IO على إدخال/إخراج الملفات فقط؛ بل يشمل إدخال/إخراج المستخدم أيضًا، ويمكن استخدامه لصنع برنامج أهلا بالعالم تقليدي:
main :: IO ()
main = do
  putStrLn "Hello, world!"
  putStrLn "What is your name, user?"
  name <- getLine
  putStrLn ("Nice to meet you, " ++ name ++ "!")

وعند إزالة السكر النحوي، يُترجم إلى سلسلة مونايدية كما يلي (>> هو متغير لـ عند تجاهل القيمة وإبقاء التأثير فقط):
main :: IO ()
main =
  putStrLn "Hello, world!" >>
  putStrLn "What is your name, user?" >> 
  getLine >>= (\name ->
    putStrLn ("Nice to meet you, " ++ name ++ "!"))

 مونايد الكاتب (جافا سكريبت)  
من الحالات الشائعة الأخرى تسجيل ملف سجل أو تتبع تقدم البرنامج. أحيانًا يرغب المبرمج بتسجيل بيانات تقنية أكثر لأغراض تحليل الأداء أو التنقيح.  مونايد الكاتب أو Writer يُستخدم لتوليد مخرجات إضافية تتراكم خطوة بخطوة.

ولتوضيح أن نمط المونايد لا يقتصر على لغات البرمجة الدالية، يعرض هذا المثال مونايد Writer باستخدام جافا سكريبت.

أولًا، تُستخدم مصفوفة (مع أطراف متداخلة) لبناء نوع Writer كقائمة متصلة.  
تُخزن القيمة الأساسية في الموقع 0 من المصفوفة، والموقع 1 يحمل سلسلة من الملاحظات الإضافية:
const writer = value => [value, []];

تعريف  بسيط أيضًا:
const unit = value => [value, []];

ويكفي استخدام  لتعريف دوال بسيطة تُخرج كائنات Writer مع ملاحظات تنقيح:
const squared = x => [x * x, [`${x} was squared.`]];
const halved = x => [x / 2, [`${x} was halved.`]];

لكن المونايد الحقيقي يحتاج إلى ، والذي في حالة Writer يعني فقط دمج ناتج الدالة مع سلسلة الملاحظات:
const bind = (writer, transform) => {
    const [value, log] = writer;
    const [result, updates] = transform(value);
    return [result, log.concat(updates)];
};

 مثال على تكوين العمليات في موناد الكاتب 

يمكن الآن ربط الدوال النموذجية باستخدام ، ولكن تعريف نسخة من تركيب العمليات المونادية (تُسمى pipelog هنا) يتيح تطبيق هذه الدوال بشكل أكثر إيجازًا:
const pipelog = (writer, ...transforms) =>
    transforms.reduce(bind, writer);

والنتيجة النهائية هي فصل واضح بين مراحل الحساب وتسجيلها للمراجعة لاحقًا:
pipelog(unit(4), squared, halved);
// كائن writer الناتج = [8, ['4 was squared.', '16 was halved.']]

 موناد البيئة 

موناد البيئة (ويُسمى أيضًا "موناد القارئ" أو "موناد الدالة") يتيح تنفيذ عمليات تعتمد على قيم من بيئة مشتركة. المُنشئ النوعي للموناد يُحوّل النوع  إلى دوال من النوع ، حيث  هو نوع البيئة المشتركة. الدوال المونادية تكون:

بعض العمليات المفيدة في هذا السياق هي:

تُستخدم عملية  لاسترجاع السياق الحالي، بينما تُستخدم  لتنفيذ عملية ضمن سياق فرعي مُعدل. ومثل موناد الحالة، يمكن تنفيذ العمليات في موناد البيئة بتوفير قيمة بيئة وتطبيقها على نسخة من الموناد.

من الناحية الشكلية، تُعادل القيمة في موناد البيئة دالةً ذات وسيط إضافي غير مُسمى؛ أما  و فتكافئان التراكبين  و في حساب التراكب سكي.

 موناد الحالة 
يسمح موناد الحالة للمُبرمج بإرفاق معلومات حالة من أي نوع بعملية حسابية. لأي نوع قيمة معين، فإن النوع المقابل في موناد الحالة هو دالة تقبل حالة وتُخرج حالة جديدة (من النوع s) بالإضافة إلى قيمة راجعة (من النوع t). وهذا يشبه موناد البيئة، لكن مع إرجاع حالة جديدة، مما يسمح بنمذجة بيئة "قابلة للتغيير".

type State s t = s -> (t, s)

لاحظ أن هذا الموناد يأخذ وسيط نوع، هو نوع معلومات الحالة. تُعرف العمليات المونادية كما يلي:

-- "return" تُنتج القيمة المُعطاة دون تغيير الحالة.
return x = \s -> (x, s)
-- "bind" تُعدل m بحيث تُطبق f على نتيجتها.
m >>= f = \r -> let (x, s) = m r in (f x) s

عمليات الحالة المفيدة تشمل:

get = \s -> (s, s) -- فحص الحالة في هذه النقطة من الحساب.
put s = \_ -> ((), s) -- استبدال الحالة.
modify f = \s -> ((), f s) -- تحديث الحالة

عملية أخرى تطبق موناد الحالة على حالة ابتدائية معينة:

runState :: State s a -> s -> (a, s)
runState t s = t s

كتل "do" في موناد الحالة هي تسلسلات من العمليات التي يمكنها فحص وتحديث بيانات الحالة.
بشكل غير رسمي، تُحوّل مونايد الحالة من نوع الحالة  نوع القيم المرجعية  إلى دوال من النوع ، حيث  هو نوع الحالة الأساسية. دوال  و تُعرّف كالتالي:
.

من وجهة نظر نظرية التصنيف، يتم اشتقاق مونايد الحالة من الاقتران بين دالة الضرب ودالة الأس الأسي، والذي يوجد في أي فئة مغلقة ديكارتيًا حسب التعريف.

 مونايد الاستمرارية 

مونايد الاستمرارية بنوع مرجعي  تُحوّل النوع  إلى دوال من النوع . تُستخدم هذه المونايد لنمذجة الاستمرارية. ودوال return وbind كما يلي:

دالة نداء مع الاستمرار الحالي تُعرّف كما يلي:

 تسجيل البرنامج 

الكود التالي هو كود وهمي .  لنفترض أن لدينا دالتين foo وbar، بأنواع:
foo : int -> int
bar : int -> int

أي أن كلا الدالتين تأخذ عددًا صحيحًا وتعيد عددًا صحيحًا آخر. يمكننا حينها تطبيق الدالتين بالتتابع بهذا الشكل:
foo (bar x)

والناتج هو نتيجة تطبيق foo على نتيجة bar المطبقة على x.

لكن، إذا كنا نقوم بتصحيح الأخطاء في البرنامج، ونرغب بإضافة رسائل تسجيل إلى foo وbar، فسنغير التواقيع لتصبح:
foo : int -> int * string
bar : int -> int * string

بحيث تُعيد كل دالة زوجًا يحتوي على نتيجة التطبيق (عدد صحيح)، ورسالة تسجيل تحتوي على معلومات حول الدالة المطبقة والدوال السابقة.

لكن هذا يعني أننا لم نعد قادرين على تركيب الدوال foo وbar، لأن نوع الإدخال int لا يتوافق مع نوع الإخراج int * string. ورغم أنه يمكننا استعادة إمكانية التركيب بتعديل أنواع كل دالة إلى int * string -> int * string، إلا أن هذا سيتطلب منا كتابة كود متكرر في كل دالة لاستخراج العدد من الزوج، وهذا قد يصبح مرهقًا مع ازدياد عدد هذه الدوال.

بدلًا من ذلك، لنقم بتعريف دالة مساعدة لتجريد هذا التكرار:
bind : int * string -> (int -> int * string) -> int * string

الدالة bind تأخذ زوجًا من عدد صحيح وسلسلة نصية، ثم تأخذ دالة (مثل foo) تُحوّل عددًا صحيحًا إلى زوج عدد وسلسلة. ناتجها هو زوج عدد وسلسلة، وهو نتيجة تطبيق الدالة على العدد الموجود داخل الزوج الأصلي. بهذه الطريقة، نكتب الكود التكراري مرة واحدة فقط في bind.

وهكذا نستعيد بعض القدرة على التركيب. على سبيل المثال:
bind (bind (x,s) bar) foo

حيث (x,s) هو زوج عدد صحيح وسلسلة نصية.

لإيضاح الفوائد أكثر، لنُعرّف عاملًا (operator) بديلاً لدالة bind:
(>>=) : int * string -> (int -> int * string) -> int * string

بحيث يصبح t >>= f مساويًا لـbind t f.

وبذلك يصبح المثال السابق:
((x,s) >>= bar) >>= foo

وأخيرًا، نُعرّف دالة جديدة لتجنب كتابة (x, "") كل مرة نريد فيها إنشاء رسالة تسجيل فارغة:
return : int -> int * string
الذي يلف x في الزوج المرتب الموضح أعلاه.

النتيجة هي سلسلة لمعالجة تسجيل الرسائل:
((return x) >>= bar) >>= foo

وهذا يسمح لنا بتسجيل تأثيرات bar وfoo على x بسهولة أكبر.

int * string تمثل قيمة مونادية مشفرة بشكل تقريبي. الدالتان bind وreturn تشبهان الدوال التي تحمل نفس الأسماء في الموناديات.
في الواقع، int * string وbind وreturn تشكل مونادًا.

 المونادات الجمعّية 
الموناد الجمعّي هو موناد مزود بعملية ثنائية إضافية مغلقة، إبدالية وترابطية تُسمى mplus وعنصر محايد تحتها يُسمى mzero.
يمكن اعتبار موناد Maybe جمعيًا، حيث يكون Nothing هو  وتغييرة على عامل فصل منطقي كـ.
وأيضًا List هو موناد جمعي، حيث القائمة الفارغة [] تعمل كـ وعامل الربط ++ يعمل كـ.

بديهيًا، يمثل  غلافًا موناديًا لا يحتوي على قيمة من النوع الأساسي، ولكنه يعتبر "صفرًا" (بدلًا من "واحد") لأنه يعمل كعنصر ماص لـ، حيث يعيد  كلما تم ربطه بدالة مونادية.
هذه الخاصية ثنائية الجانب، فـ سيعيد أيضًا  عندما يتم ربط أي قيمة بـموناد 0 (عدد).

من الناحية النظرية للفئات، يؤهل الموناد الجمعي ليكون مرة كمونويد على الدوال المونادية مع  (كما تفعل جميع المونادات)، ومرة أخرى على القيم المونادية عبر .

 المونادات الحرة 
أحيانًا قد يكون المخطط العام للموناد مفيدًا، لكن لا يوجد نمط بسيط يوصي بموناد معين.
هنا يأتي دور الموناد الحر; ككائن حر في فئة المونادات، يمكنه تمثيل بنية مونادية دون قيود محددة بخلاف قوانين الموناد نفسها.
كما يربط المونويد الحر العناصر دون تقييم، يسمح الموناد الحر بربط الحسابات مع علامات لتلبية نظام الأنواع، لكنه لا يفرض دلالات أعمق.

على سبيل المثال، بالعمل فقط من خلال العلامتين Just وNothing، فإن موناد Maybe هو في الحقيقة موناد حر.
أما موناد List، فلا يعد مونادًا حرًا لأنه يحمل حقائق إضافية محددة عن القوائم (مثل ).
مثال آخر هو موناد حر مجرد:
data Free f a
  = Pure a
  | Free (f (Free f a))

unit :: a -> Free f a
unit x = Pure x

bind :: Functor f => Free f a -> (a -> Free f b) -> Free f b
bind (Pure x) f = f x
bind (Free x) f = Free (fmap (\y -> bind y f) x)
ومع ذلك، ليست المونادات الحرة مقصورة على قائمة مرتبطة كما في هذا المثال، بل يمكن بناؤها حول هياكل أخرى مثل الشجرة.

قد يبدو استخدام المونادات الحرة غير عملي في البداية، لكن طبيعتها الرسمية مناسبة جدًا للمشاكل النحوية.
يمكن استخدام الموناد الحر لتتبع النحو والنوع مع ترك الدلالات لوقت لاحق، وقد وجد استخدامًا في المحللات والمفسرات.
وقد طبقها آخرون على مشاكل تشغيلية وديناميكية أكثر، مثل توفير المُكررون داخل لغة برمجة.

 الكومونادات 
إلى جانب توليد المونادات مع خصائص إضافية، يمكن لأي موناد معين أيضًا تعريف كوموناد.
مفهوميًا، إذا كانت المونادات تمثل حسابات مبنية على قيم أساسية، فيمكن اعتبار الكومونادات تقليصات تعود إلى القيم.
الكود المونادي، بمعنى ما، لا يمكن "فك تغليفه" بالكامل؛ فبمجرد أن تُلف القيمة داخل موناد، تبقى محصورة هناك مع أي تأثيرات جانبية (وهذا أمر جيد في البرمجة الوظيفية الصرفة).
لكن أحيانًا تكون المشكلة أكثر عن استهلاك بيانات سياقية، وهو ما يمكن للكومونادات نمذجته بشكل صريح.

تقنيًا، الكوموناد هو الثنائي التصنيفي للموناد، مما يعني بشكل غير رسمي أنه يحتوي على نفس المكونات المطلوبة، ولكن مع عكس اتجاه توقيعات الأنواع.
ابتداءً من تعريف الموناد المرتكز على ، يتكون الكوموناد من:
 منشئ نوع  الذي يحدد النوع الأعلى 
 عكس ، ويسمى هنا counit، ويستخرج القيمة الأساسية من الكوموناد:
  counit(wa) : W T → T
 عكس  (يُمثّل أيضًا بـ =>>) الذي يمدد سلسلة الدوال المختزلة:
  (wa =>> f) : (W U, W U → T) → W T
يجب أن تحقق  و أيضًا قوانين ثنائية للموناد:
  counit ∘ '''(''' (wa =>> f) → wb ''')'''  ↔  f(wa) → b  
  wa =>> counit  ↔  wa  
  wa '''(''' (=>> f(wx = wa)) → wb (=>> g(wy = wb)) → wc ''')'''  ↔  '''(''' wa (=>> f(wx = wa)) → wb ''')''' (=>> g(wy = wb)) → wc
مماثلًا للمونادات، يمكن أيضًا اشتقاق الكومونادات من الفانكتورات باستخدام عكس :
 duplicate تأخذ قيمة كومونادية موجودة وتلفها بطبقة أخرى من البنية الكومونادية:
  duplicate(wa) : W T → W (W T)
بينما تُعكس عمليات مثل ، إلا أن الكوموناد لا يعكس الدوال التي يعمل عليها، ونتيجة لذلك، فإن الكومونادات لا تزال فانكتورات مع ، وليست دال (رياضيات)ات.
التعريف البديل باستخدام  و و يجب أن يحترم قوانينه الخاصة للكوموناد:
  ((map duplicate) ∘ duplicate) wa  ↔  (duplicate ∘ duplicate) wa  ↔  wwwa  
  ((map counit) ∘ duplicate)    wa  ↔  (counit ∘ duplicate)    wa  ↔  wa  
  ((map map φ) ∘ duplicate)     wa  ↔  (duplicate ∘ (map φ))   wa  ↔  wwb
وكما هو الحال مع المونادات، يمكن تحويل الشكلين تلقائيًا:
  (map φ) wa    ↔  wa =>> (φ ∘ counit) wx  
  duplicate wa  ↔  wa =>> wx  

  wa =>> f(wx)  ↔  ((map f) ∘ duplicate) wa  
مثال بسيط هو كوموناد المنتج، الذي ينتج قيمًا بناءً على قيمة إدخال وبيانات بيئة مشتركة.
في الواقع، كوموناد Product هو ببساطة العكس للكوموناد Writer وفعليًا مماثل لكوموناد Reader (كلاهما مذكور أدناه).
يختلف Product وReader فقط في توقيعات الدوال التي يقبلانها، وكيف يكملان تلك الدوال بتغليف أو فك تغليف القيم.

مثال أقل بساطة هو كوموناد التدفق، الذي يمكن استخدامه لتمثيل الجريان وربط فلاتر بالإشارات الواردة باستخدام .
في الحقيقة، رغم أن الكومونادات ليست شائعة مثل المونادات، فقد وجد الباحثون أنها مفيدة بشكل خاص لتحليل التدفق ونمذجة برمجة تنقل المعطيات.

لكن بسبب تعريفها الصارم، لا يمكن ببساطة تحريك الكائنات ذهابًا وإيابًا بين المونادات والكومونادات.
كتجريد أعلى، يمكن أن تضمّن الأسهم كلا الهيكلين، لكن إيجاد طرق أكثر تفصيلًا لدمج كود الموناد والكوموناد هو مجال بحث نشط.

 انظر أيضًا 

بدائل لنمذجة العمليات الحسابية:
 أنظمة التأثير (وخاصة معالجات التأثير الجبري) هي طريقة مختلفة لوصف التأثيرات الجانبية على شكل أنواع
 نوع التفرد هو نهج ثالث لمعالجة التأثيرات الجانبية في اللغات الوظيفية

مفاهيم تصميم ذات صلة:
 البرمجة الموجهة بالسمات تركز على فصل الشيفرات المساعدة والثانوية لتحسين التركيبية والبساطة
 عكس التحكم هو مبدأ تجريدي لاستدعاء دوال معينة من إطار عمل شامل
 صنف نوعي هو ميزة لغوية محددة تُستخدم لتنفيذ المونادات وبُنى أخرى في هاسكل
 نموذج التصميم ديكور هو وسيلة أكثر واقعية ومرتجلة لتحقيق فوائد مماثلة في البرمجة الكائنية التوجه

تعميمات المونادات:
 الدالة التطبِيقية تعمم من المونادات من خلال الاحتفاظ فقط بـ  والقوانين المرتبطة بها مع 
 السهم يستخدم بُنى إضافية لدمج الدوال العادية والمونادات ضمن واجهة موحدة
 محوّل الموناد يعمل على مونادات منفصلة لدمجها بشكل تركيبي

 الملاحظات 

 المراجع 

 وصلات خارجية 

مراجع من هاسكل ويكي:
 "كل شيء عن المونادات" (أصلًا من تأليف جيف نيوبرن) — مناقشة شاملة لجميع المونادات الشائعة وكيفية عملها في هاسكل؛ تتضمن تشبيه "خط التجميع الآلي".
 "موسوعة الأصناف النوعية" (أصلًا من تأليف برينت يورجي) — شرح مفصل حول كيفية ترابط الأصناف النوعية الأساسية في هاسكل، بما في ذلك المونادات.

دروس تعليمية:
 "حفنة من المونادات" (من كتاب هاسكل الإلكتروني تعلم هاسكل من أجل الخير العظيم! — فصل يُقدم المونادات انطلاقًا من صنفي الدوال: "فنكتر" و"تطبيقية"، مع أمثلة.
 "من أجل المزيد من المونادات" — فصل ثانٍ يشرح مزيدًا من التفاصيل والأمثلة، بما في ذلك موناد الاحتمالية لسلاسل سلسلة ماركوف.
 "الدوال، التطبيقية، والمونادات بالصور" (بقلم أديتيا بهارجافا) — درس تعليمي سريع، فكاهي، ومرئي عن المونادات.

حالات مثيرة للاهتمام:
 "أنابيب يونكس كمونادات IO" (بقلم أوليغ كيسليوف) — مقالة قصيرة تشرح كيف أن أنابيب يونكس تُعد فعليًا مونادية.
 برمجة سكالا الاحترافية: أنماط تصميم مونادية للويب (بقلم غريغوري ميريديث) — مخطوطة كاملة غير منشورة حول كيفية تحسين العديد من جوانب تطوير الويب في سكالا (لغة برمجة) باستخدام المونادات.

تصنيف:علم الحاسوب في 1991
تصنيف:برمجة وظيفية
تصنيف:نماذج تصميم البرمجيات
تصنيف:تعبيرات اصطلاحية في البرمجة