۱۶ - ۵قوانین فانکتور
نمونههای تایپکلاسِ 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 b
f
با تایپکلاسِ Functor
محدود شده؛ از این تعریف، تنها چیزی که راجع بهش میدونیم همینه. همونطور که در پلیمورفیسم با محدودیت تایپکلاسی دیدیم، اینجا f
میتونه هر تایپی که یه نمونه از Functor
داره باشه. عملیات ِ اصلی که این تایپکلاس برای تایپهاش تأمین میکنه، همین fmap
ِه. به دلیلِ اینکه f
در طولِ تایپِ fmap
یکنواخت میمونه، هر تایپی که باشه میدونیم یک آرگومان میگیره ( مثل f a
و f b
) و ساختارایه که تابع رو از روش لیفت میکنیم تا به مقدارِ داخلیش اعمال کنیم.