۲۰ - ۳تابع sequenceA

با چندتا مثال از ‏‎sequenceA‎‏ شروع می‌کنیم، چون از ‏‎traverse‎‏ ساده‌تره. از تایپ سیگنچر‌ِش در بالا می‌بینید تأثیری که ‏‎sequenceA‎‏ میذاره، جابجاییِ دو بافت (یا ساختار) با هم دیگه‌ست. به خودیِ‌خود امکانِ اعمال ِ تابع به ‏‎a‎‏ رو نمیده؛ فقط جای لایه‌های ساختاری رو با هم عوض می‌کنه. اینها رو:

Prelude> sum [1, 2, 3]
6
Prelude> fmap sum [Just 1, Just 2, Just 3]
[1,2,3]
Prelude> (fmap . fmap) sum Just [1, 2, 3]
Just 6
Prelude> fmap product [Just 1, Just 2, Nothing]
[1,2,1]

با اینها مقایسه کنین:

Prelude> fmap Just [1, 2, 3]
[Just 1,Just 2,Just 3]
Prelude> sequenceA $ fmap Just [1, 2, 3]
Just [1,2,3]
Prelude> sequenceA [Just 1, Just 2, Just 3]
Just [1,2,3]
Prelude> sequenceA [Just 1, Just 2, Nothing]
Nothing
Prelude> fmap sum $ sequenceA [Just 1,Just 2,Just 3]
Just 6
Prelude> let xs = [Just 3, Just 4, Nothing]
Prelude> fmap product (sequenceA xs)
Nothing

اول با استفاده از ‏‎sequenceA‎‏ ساختار‌ها رو با هم جابجا کردیم – یعنی یه لیست از مقادیرِ ‏‎Maybe‎‏ رو به یه ‏‎Maybe‎‏ از لیستِ مقادیر تبدیل کردیم. در مثال‌های بعد، یه تابع رو از روی ساختار ِ ‏‎Maybe‎‏ لیفت کردیم و به لیستِ داخل‌ش اعمال کردیم (البته اگه بعد از اعمال ِ ‏‎sequenceA‎‏ به یه مقدارِ ‏‎Just a‎‏ رسیده بودیم؛ چون مقادیرِ ‏‎Nothing‎‏ لیستی برای اعمال شدن ندارن).

ارزش داره اشاره کنیم که ماژول ِ ‏‎Data.Maybe‎‏ یه تابع به اسمِ ‏‎catMaybes‎‏ داره که یه راه متفاوت برای کار با یه لیست از ‏‎Maybe‎‏‌ها ارائه میده:

Prelude> import Data.Maybe
Prelude> catMaybes [Just 1, Just 2, Just 3]
[1,2,3]
Prelude> catMaybes [Just 1, Just 2, Nothing]
[1,2]
Prelude> let xs = [Just 1, Just 2, Just 3, Nothing]
Prelude> sum $ catMaybes xs
6
Prelude> fmap sum $ sequenceA xs
Nothing

با استفاده از ‏‎catMaybes‎‏، حتی با وجودِ مقدار یا مقادیرِ ‏‎Nothing‎‏ هم میشه بقیه‌ی مقادیر رو پردازش کرد.