إذا قمت بفحص النوع foldMap
class Foldable f where
foldMap :: Monoid m => (a -> m) -> f a -> m
سترى أنه يحتوي على نوع غير محدود m
. بشكل عام عندما يحدث هذا يعني ذلك m
ممكن ان يكون اى شئ, ، ولكن هنا يقيد أيضا m
مع Monoid m
. هذا هو Monoid
يأتي من.
تجدر الإشارة إلى أنه إذا لم يكن لدينا Monoid
على سبيل المثال ، من الصعب للغاية تحديد وظيفة تُرجع قيمة "يمكن أن تكون أي شيء". إذا حاولت ذلك ، فستجد أنه من المستحيل تقريبًا (بدون "الغش").
impossible :: Int -> b -- no constraints on `b` at all!
impossible i = ...?
لكن من السهل جدًا أن نعرف قليلاً عن النوع
veryPossible :: Num b => Int -> b
veryPossible i = fromIntegral i
-- or
veryPossible2 i = fromIntegral (i * i) + fromIntegral i
كمثال آخر ، فكر في نوع التعبير
expr m = mconcat [m <> m <> mempty, mempty <> m]
نظرًا لأن هذا التعبير مبني على أساس بعض القيمة غير المعروفة m
ويستخدم فقط الوظائف في Monoid
الطبقة أو مشتقاتها ، يعكس ذلك. النوع الأكثر عمومية من expr
هو
expr :: Monoid m => m -> m
مرة أخرى هنا ، m
هو متغير نوع مجاني مقيد ليكون بعض Monoid
.
السبب foldMap
يتيح لك استخدام Monoid
الوظائف هي لأنه يقيد بشكل صريح أنواع الأشياء m
في نوع التوقيع يمكن أن يكون. من خلال وضع القيود هناك ، نكتسب المزيد من القوة للتلاعب بها.