۲۴ - ۵دونَد؟

‏‎Monad‎‏ چطور؟ ترکیب ِ دو تایپِ دلخواه که نمونه ِ ‏‎Monad‎‏ دارن هیچ اشکالی نداره. تو اون مثالی که با استفاده از ‏‎Compose‎‏ تایپ‌های ‏‎Maybe‎‏ و لیست (که هردوشون نمونه ِ ‏‎Monad‎‏ دارن) رو ترکیب کردیم مشکلی نبود. با این حال، تایپِ حاصل از ترکیب‌شون، یه ‏‎Monad‎‏ نمیده.

مشکل در کمبودِ اطلاعات‌ه. هردو تایپ‌هایی که ‏‎Compose‎‏ باهاشون کار می‌کنه پلی‌مورفیک اند، پس وقتی می‌خواین برای ‏‎Monad‎‏ بایند رو تعریف کنین، یعنی می‌خواین دوتا بایند ِ پلی‌مورفیک رو به یک بایند ترکیب کنین، که چنین چیزی ممکن نیست:

{-# LANGUAGE InstanceSigs #-}

-- .غیرممکن
instance (Monad f, Monad g)
      => Monad (Compose f g) where
  return = pure

  (>>=) :: Compose f g a
        -> (a -> Compose f g b)
        -> Compose f g b
  (>>=) = ???

این دوتا، تایپ‌هایی‌اند که می‌خوایم ترکیب کنیم، چون ‏‎f‎‏ و ‏‎g‎‏ هردوشون لزوماً موند هستن و نمونه ِ ‏‎Monad‎‏ ِ خودشون رو دارن:

Monad f => f a -> (a -> f b) -> f a -> f b
Monad g => g a -> (a -> g b) -> g a -> g b

با توجه به اونها، چنین بایندی می‌خوایم بنویسیم:

   (Monad f, Monad g)
=> f (g a) -> (a -> f (g b)) -> f (g b)

یا با فرمولی متفاوت:

   (Monad f, Monad g)
=> f (g (f (g b))) -> f (g b)

و چنین چیزی غیرممکنه. هیچ راه خوبی برای ‏‎join‎‏ کردنِ اون ‏‎f‎‏ و ‏‎g‎‏ ِ نهایی نیست. تمرینِ خیلی خوبیه که سعی کنین طوری بنویسین که کار کنه، چون به موانعِ آموزنده‌ای می‌خورین. می‌تونین مقاله‌ی مارک پی . جونز و لاک دوپونشیل با عنوانِ ترکیب موندها رو هم بخونین.

خبری از بوریتوی مجانی نیست

حالا که دیدیم گرفتنِ یه ‏‎Monad‎‏ ِ دیگه از ترکیب ِ دو تایپِ دلخواه که نمونه ِ ‏‎Monad‎‏ دارن غیرممکنه، چی کار می‌تونیم انجام بدیم تا برای ترکیب‌های تایپ‌ها، نمونه ِ ‏‎Monad‎‏ داشته باشیم؟ جواب، موند ترانسفورمرها اند. بعد از کمی استراحت (با تمرین) توضیح میدیم.