۱۵ - ۱۴قدرت ممکنه ضعف باشه
وقتی هسکلنویسها میگن یه جبر قویه، منظورشون تعداد عملیاتهاییه که اون جبر ارائه میده؛ متعاقباً کارهایی هم که با هر نمونهای از اون جبر میشه انجام داد (بیربط به تایپ) بیشتر میشه.
نه تمایلی داریم، نه هیچ وقت همهی جبرهامون رو تا جای ممکن بزرگ میکنیم؛ بعضی نوعدادهها هستن که کاربردهای خیلی مفیدی رو ارائه میدن، ولی نمیتونن همه چیز از یه جبر ِ بزرگ رو ارضا کنن. مثلاً همین تایپِ NonEmpty. اگه برنامهنویسِ با تجربهای هستین، خوب فکر کنین ببینین چندبار میخواستین لیستتون هیچ وقت خالی نباشه؟ برای تضمین موارد مشابه، و گویاتر کردن تایپها، از تایپهایی مثل NonEmpty استفاده میکنیم.
ولی NonEmpty هیچ مقدارِ همانیای برای عملیاتِ ترکیبی (mappend) در Monoid نداره. پس شرکتپذیری رو نگه میداریم و مقدار همانی، به همراه قانونهای همانی ِ چپ و راست رو حذف میکنیم. چنین چیزی نیاز به Semigroup برای یه نوعداده رو معرفی میکنه.
واضحترین موردی که نشون میده مانوید از نیمگروه قویتره، اینه که همهی عملیاتها و قانونهاییه که Semigroup ارائه میده، زیر مجموعهی عملیاتها و قانونهای مانوید ِه. به عبارت دیگه مانوید یه ابرمجموعه از نیمگروه ِه؛ بر همین مبنا، هرچیزی که مانوید هست، نیمگروه هم هست. امید هست که در نسخهی بعدیِ GHC، Semigroup سوپرکلاس ِ Monoid بشه.
class Semigroup a => Monoid a where
...بالاتر رابطهی معکوس بین تعداد عملیاتهای مجاز برای یه تایپ و تعداد تایپهایی که ارضاکننده هستن رو توجیه کردیم. همین رابطهی معکوس رو بین تعداد عملیاتها و قوانینی که یه جبر تقاضا داره، و تعداد نوعدادههایی که میتونن نمونههای قانونمند از اون جبر ارائه بِدن میشه دید.
در مثال زیر، a میتونه هر چیزی باشه، اما هیچ عملیاتی هم براش نیست – فقط میتونیم خودش رو برگردونیم.
id :: a -> aتعداد تایپها: بینهایت – سور عمومی، پس میتونه هر تایپی باشه.
تعداد عملیاتها: یک (اگه بشه اسمش رو عملیات گذاشت)؛ ارجاع به مقدار ورودی.
در تابعِ inc، تایپِ a همهی عملیاتهای Num رو داره، یعنی کارهای بیشتری میشه انجام داد. به این معنی هم هست که دیگه مجموعهی تایپهایی که میتونن محدودیت ِ Num رو ارضا کنن متناهی شده (هر تایپی که تو دنیا وجود داره نمیشه):
inc :: Num a => a -> aتعداد تایپها: هرچیزی که Num داره. صفر تا خیلی.
تعداد عملیاتها: ۷ تا متود ِ Num.
در مثال بعد، تایپمون Int ِه، که خیلی عملیاتهای بیشتری هم نسبت به Num در اختیار میذاره:
somethingInt :: Int -> Intتعداد تایپها: یک، فقط Int.
تعداد عملیاتها: خیلی بیشتر از ۷ تا. علاوه بر Num، تایپِ Int از تایپکلاسهای Bounded، Enum، Eq، Integral، Ord، Read، Real، و Show هم نمونه داره. حتی تابعهایی هم میشه تعریف کرد که روی یه مقدار دلخواه از تایپهای معیّن تطبیقِ الگو میکنن و مقادیرِ دلخواه از همون تایپ رو برمیگردونن. پلیمورفیسم فقط برای استفادهی دوباره از کُد کاربرد نداره؛ به دردِ بیانِ نیت از طریقِ پارامتریسیته هم میخوره، یعنی کمک میکنه هرکسی کُد رو میخونه، قصدِ نویسنده رو هم متوجه بشه.
هرجا Monoid زیادی قوی بود یا بیشتر از نیازمون بود، میشه از Semigroup استفاده کنیم. اگه براتون سؤال شده که چی از Semigroup ضعیفتره، جواب ماگما هست که از حذفِ شرکتپذیری بدست میاد. احتمالش کمه تو هسکلِ روزمره لازم باشه، ولی اگه میخواین به بقیه پُز بدین، دونستنِ اینکه از نیمگروه ضعیفتره کاربرد داره.