۱۶ - ۳اِف‌مَپ اینجا، اف‌مپ اونجا، اف‌مپ همه‌جا

‏‎fmap‎‏ رو قبلاً دیدیم، اما برای چیزی غیر از لیست‌ها ازش استفاده نکردیم. با لیست‌ها انگار عین ‏‎map‎‏ کار می‌کنه:

Prelude> map (\x -> x > 3) [1..6]
[False,False,False,True,True,True]
Prelude> fmap (\x -> x > 3) [1..6] 
[False,False,False,True,True,True]

البته لیست یکی از تایپ‌هایی‌ه که یه نمونه از تایپکلاسِ ‏‎Functor‎‏ داره، ولی استفاده از ‏‎fmap‎‏ با لیست، چون دقیقاً مثلِ ‏‎map‎‏ کار می‌کنه، خیلی چیزِ بارِزی نیست. با این حال لیست تنها تایپی که ‏‎Functor‎‏ داره نیست، و ‏‎fmap‎‏ می‌تونه یه تابع رو از روی ( یا از اطراف) هر کدوم از اون ساختار‌های فانکتوری اعمال کنه، در صورتی که ‏‎map‎‏ نمی‌تونه:

Prelude> map (+1) (Just 1)

Couldn't match expected type ‘[b]’
  with actual type ‘Maybe a0’

Relevant bindings include
  it :: [b] (bound at 16:1)
In the second argument of ‘map’
  namely ‘(Just 1)’
In the expression: map (+1) (Just 1)

Prelude> fmap (+1) (Just 1)
Just 2

جالب شد! دیگه چی؟

-- !با یه توپل
Prelude> fmap (10/) (4, 5)
(4,2.0)

-- !Either با
Prelude> let rca = Right "Chris Allen"
Prelude> fmap (++ ", Esq.") rca
Right "Chris Allen, Esq."

نحوه‌ی اختصاصی شدنِ تایپِ ‏‎fmap‎‏ برای تایپ‌های مختلف رو میشه اینجا دید:

type E e = Either e
type C e = Constant e
type I = Identity
-- Functor f =>
fmap :: (a -> b) ->     f a ->     f b
     :: (a -> b) ->   [ ] a ->   [ ] b
     :: (a -> b) -> Maybe a -> Maybe b
     :: (a -> b) ->   E e a ->   E e b
     :: (a -> b) ->  (e,) a ->  (e,) b
     :: (a -> b) ->     I a ->     I b
     :: (a -> b) ->   C e a ->   C e b

اگه از ۸ GHC یا جدیدتر استفاده می‌کنین، چنین چیزی رو خودتون هم تو REPL می‌تونین ببینین:

Prelude> :set -XTypeApplications

Prelude> :type fmap @Maybe
fmap @Maybe ::
    (a -> b) -> Maybe a -> Maybe b

Prelude> :type fmap @Either
fmap @Either ::
    (a -> b) -> Either t a -> Either t b

شاید متوجه شده باشین که در توپل و ‏‎Either‎‏، اولین آرگومان‌شون ( که در جدولِ بالا با ‏‎e‎‏ نشون دادیم) توسطِ ‏‎fmap‎‏ نادیده گرفته شده. یه ذره جلوتر دلیلِ چنین چیزی رو میگیم. قبل‌ش ببینیم یه فانکتور چطور درست میشه. بعد برمی‌گردیم و حسابی این مبحث رو ادامه میدیم.