۱۶ - ۵قوانین فانکتور
نمونههای تایپکلاسِ Functor باید از دو قانون تبعیت کنن. درک این قوانین برای درکِ فانکتور و نوشتنِ نمونههای تایپکلاسیِ ترکیبپذیر و گویا خیلی مهمه.
همانی
اولین قانون، قانون ِ همانی ِه:
fmap id == idاگه تابع همانی رو fmap کنیم، باید همون جوابی رو بده که نتیجهی اعمال ِ خودِ تابعِ همانی به اون مقداره. با نگاشت ِ id نباید هیچ تغییری در ساختار ِ بیرونی (f) که داریم از روش نگاشت میکنیم پیش بیاد. به همین دلیل هم با id یکسانه. اگه از نگاشت ِ تابعِ a -> b از روی یه ساختار، چیزِ جدیدی عایدمون نمیشه، هیچ چیز هم نباید تغییر کنه:
Prelude> fmap id "Hi Julie"
"Hi Julie"
Prelude> id "Hi Julie"
"Hi Julie"میتونین با چندتا ساختار ِ دیگه هم امتحان کنین.
ترکیبپذیری
قانون ِ دوم برای فانکتور، قانونِ ترکیبپذیری ِه:
fmap (f . g) == fmap f . fmap gاین قانون مرتبط با ترکیبپذیری ِ fmap ِه. اگه دو تابعِ f و g رو با هم ترکیب کنیم، بعد اون رو از روی یه ساختار fmap کنیم، باید همون جوابی رو بده که اگه اول fmap ِشون میکردیم بعد ترکیبِشون میکردیم:
Prelude> fmap ((+1) . (*2)) [1..5]
[3,5,7,9,11]
Prelude> fmap (+1) . fmap (*2) $ [1..5]
[3,5,7,9,11]اگه تعریفِ یه fmap اینطور کار نمیکنه، فانکتور ِ درستی نیست.
حفظ ِ ساختار
هردوی این قانونها به اون قانون ِ اساسی که ساختار باید دستنخورده باقی بمونه اشاره دارن.
تنها چیزی که اجازه داریم از f بدونیم، اینه که Functor داره:
fmap :: Functor f => (a -> b) -> f a -> f bf با تایپکلاسِ Functor محدود شده؛ از این تعریف، تنها چیزی که راجع بهش میدونیم همینه. همونطور که در پلیمورفیسم با محدودیت تایپکلاسی دیدیم، اینجا f میتونه هر تایپی که یه نمونه از Functor داره باشه. عملیات ِ اصلی که این تایپکلاس برای تایپهاش تأمین میکنه، همین fmap ِه. به دلیلِ اینکه f در طولِ تایپِ fmap یکنواخت میمونه، هر تایپی که باشه میدونیم یک آرگومان میگیره ( مثل f a و f b) و ساختارایه که تابع رو از روش لیفت میکنیم تا به مقدارِ داخلیش اعمال کنیم.