۲۴ - ۳دوتا فانکتور کوچولو رو درخت نشستن لیفت میکنن
کارمون رو با ترکیب ِ فانکتورها، به کمک تایپهایی که بالاتر دیدیم شروع میکنیم. میدونیم که میشه از رو Identity لیفت کرد؛ این Functor رو قبلاً دیدین:
instance Functor Identity where
fmap f (Identity a) = Identity (f a)فانکتوری که برای Identity هست در واقع هیچ کاری نمیکنه، فقط ماهیتِ Functor رو نشون میده. تابع از روی بافت ِ Identity لیفت میشه و بعد روی مقدارِ a نگاشت میشه.
اگه از f و g نمونه ِ Functor بخوایم، برای Compose هم میشه یه نمونه ِ Functor نوشت:
instance (Functor f, Functor g) =>
Functor (Compose f g) where
fmap f (Compose fga) =
Compose $ (fmap . fmap) f fgaحالا f و g هردوشون جزئی از ساختاری اند که از روش لیفت میکنیم، پس جفتشون هم باید Functor باشن. برای اینکه بتونیم تابعی رو به مقداری که کاملاً داخلِ تایپ قرار گرفته اعمال کنیم، باید بتونیم از روی هردوتای اون لایهها بِپَریم. به خاطرِ وجودِ اون دو لایه، باید دوبار fmap کنیم.
اگه برگردیم به مثالی که بالاتر داشتیم:
newtype Compose f g a =
Compose { getCompose :: f (g a) }
deriving (Eq, Show)
Compose { getCompose :: f (g a) }
Compose [] Maybe Intو از نمونه ِ Functor استفاده کنیم، میتونیم یه تابع رو به اون مقدارِ Int که لای همهی اون ساختارها پوشونده شده اعمال کنیم:
Prelude> let xs = [Just 1, Nothing]
Prelude> Compose xs
Compose {getCompose = [Just 1,Nothing]}
Prelude> fmap (+1) (Compose xs)
Compose {getCompose = [Just 2,Nothing]}این قضیه رو میشه به تعدادِ مختلفِ لایهها تعمیم داد، مثلِ زیر که یه لایه کمتر داره. این مثال شاید یادتون بیاد (از یکی از فصلهای قبل):
newtype One f a =
One (f a)
deriving (Eq, Show)
instance Functor f =>
Functor (One f) where
fmap f (One fa) = One $ fmap f faیا یه لایه ساختار بیشتر از Compose:
newtype Three f g h a =
Three (f (g (h a)))
deriving (Eq, Show)
instance (Functor f, Functor g, Functor h)
=> Functor (Three f g h) where
fmap f (Three fgha) =
Compose $ (fmap . fmap . fmap) f fghaمشابه تایپ ضرب ِ بینام (یعنی (,)) و تایپ جمع ِ بینام (Either)، تایپِ Compose هم میشه به تعدادِ دلخواه تودرتو کرد:
v :: Compose []
Maybe
(Compose Maybe [] Integer)
v = Compose [Just (Compose $ Just [1])]میشه اینطوری بهش فکر کرد که ترکیب ِ دو نوعدادهای که نمونه ِ Functor دارن، باعث ایجادِ یه نمونه ِ Functor ِ دیگه میشه. گاهی اوقات چنین چیزی رو اینطوری توصیف میکنن که فانکتورها تحتِ عملِ ترکیب بستهاند، یعنی وقتی دوتا Functor رو با هم ترکیب میکنین، یه Functor ِ دیگه میگیرین.