زبان آکادمیک که در آزمایشگاه ماند

برای دهه‌ها، هسکل در محافل دانشگاهی محدود بود. جامعه برنامه‌نویسی آن را زبانی پیچیده، غیر‌عملی و محضاً تئوریک می‌دانست. این قضاوت زمانی دگرگون شد که اکوسیستم جهانی با چالش‌های مقیاس‌پذیری، هم‌زمانی‌های سنگین و ناپایداری سیستم‌های توزیع‌شده مواجه گشت. ایده‌های هسکل یواشکی به هسته زبان‌های پرکاربرد نفوذ کردند و امروز پایه‌ی معماری راست، سوئیفت و اسکالا را شکل داده‌اند.

موج خاموش تغییر در اکوسیستم جهانی

در میانه‌های دهه ۲۰۱۰ مواضع صنعت نسبت به برنامه‌نویسی تابعی تغییر کرد. یک تایم‌لاین کوتاه از پذیرش این الگوها این تحول را نشان می‌دهد:

  • ۲۰۱۵: ری‌اکت پرپس‌های غیرقابل‌تغییر و تابع رندر خالص را معرفی کرد
  • ۲۰۱۶: ردوکس معادله state = reducer(state, action) را استاندارد کرد
  • ۲۰۱۷: پیشنهاد ری‌اکت هوکس مطرح شد؛ گذار از کلاس‌ها به توابع
  • ۲۰۱۹: راست مکانیزم مالکیت و انواع Result و Option را یکپارچه پذیرفت
  • ۲۰۲۰: سوئیفت ۵.۵ سینتکس async/await، Task و Result را عرضه کرد
  • ۲۰۲۱: Result<T> در کاتلین و Optional<T> در جاوا وارد جریان اصلی شدند
  • ۲۰۲۳: Effect-TS نسخه ۱.۰ را منتشر کرد؛ پروژه‌ای که به «هسکلِ تایپ‌اسکریپت» معروف شد
  • ۲۰۲۴: گلیم نسخه ۱.۰ برنامه‌نویسی تابعی نوع‌محور را به ماشین مجازی ارلنگ برد

سه نیروی اصلی این جابجایی معماری بودند: هم‌زمانی (ده‌ها هزار درخواست هم‌زمان قفل‌گذاری وضعیت مشترک را به چالش کشید و غیرقابل‌تغییر بودن را اجتناب‌ناپذیر کرد)، پایداری (شکست‌های جزئی در کلسترها فلسفه «اجازه به فروپاشی» را اثبات کردند) و ایمنی نوع‌ها (انواع جبری داده و تطبیق الگو باگ‌ها را کاهش دادند). هسکل دهه‌ها پیش درباره این سه محور هشدار داده بود.

سه ایده‌ای که استانداردهای جدید را دیکته کرد

توابع خالص؛ نظم مهندسی نه فلسفه ریاضی

در هسته هسکل مفهوم تابع خالص قرار دارد: ورودی ثابت تولید خروجی ثابت بدون هیچ اثر جانبی. این اصل پیاده‌سازی مهندسی قدرتمندی دارد. توابع خالص قابل‌تست‌اند (بدون نیاز به mock کردن منابع خارجی)، قابل‌موازی‌سازی‌اند (حذف وضعیت مشترک به‌طور پیش‌فرض امنیت رشته‌ها را تضمین می‌کند)، قابل‌کش‌شدن‌اند و قابل‌ترکیب‌اند. نام رسمی این خاصیت شفافیت اشاره است؛ یعنی جایگزینی یک فراخوانی با نتیجه مستقیم آن تغییر در رفتار برنامه ایجاد نمی‌کند.

برنامه‌های واقعی اما مجبورند با دیتابیس، شبکه و فایل کار کنند. راهکار هسکل حذف این تعاملات نبود، بلکه دفع آن‌ها به لبه‌های سیستم و رمزگذاری وضعیت آن‌ها در تایپ‌سیستم بود. هسکل از IO a استفاده می‌کند. راست با Result<T, E> همان هدف را پیاده می‌کند. Effect-TS با Effect<R, E, A> الزامات و خطاها را ردیابی می‌کند. نحو متفاوت است، اما فلسفه یکسان می‌ماند.

پایان رسمی reignِ null

تونی هور null را «اشتباه میلیارد دلاری» تاریخ نامید. پاسخ هسکل این بود که امکان نداشتن یک مقدار را مستقیماً در سیستم نوع‌ها مدل کند. دو نوع از این طریق محبوب شدند و امروز تقریباً در همه‌ی زبان‌های مدرن حضور دارند:

  • Maybe a — مقدار یا وجود دارد (Just a) یا وجود ندارد (Nothing)
  • Either e a — یکی از دو مسیر؛ معمولاً خطا (Left e) یا موفقیت (Right a)

این الگو قراردادهای مبهم را به تعهدات صریح تبدیل می‌کند. تابعی که Maybe User برمی‌گرداند از همان لحظه کالیبراسیون به شما یادآوری می‌کند که کاربر ممکن است پیدا نشود. تابعی که Either Error Invoice تعریف می‌کند شکست را به عنوان بخشی از جریان عادی کار معرفی می‌کند. این رویکرد قواعد پنهان مانند «خالی یعنی خطا» یا «۱- یعنی ناشناخته» را از لایه منطق خارج و به تایپ‌سیستم منتقل می‌کند جایی که کاملاً شفاف و قابل بررسی است.

مقایسه الگوهای برنامه‌نویسی تابعی و شیءگرا در زبان‌های مدرن

راست، سوئیفت و اسکالا؛ میراث‌داران جریان اصلی

در نگاه اول راست و هسکل دو قطب متضاد به نظر می‌رسند. راست زبان سیستمی با سینتکس آشنا به C است، در حالی که هسکل کاملاً تابعی و متکی به نظریه تایپ پیشرفته است. با این حال، هر دو زبان طیف وسیعی از توسعه‌دهندگان هم‌راهِ یکدیگر را جذب کرده‌اند و به دلیل نیاز به تایپ‌های جبری و چندریختی سفارشی (از طریق Trait در راست و Type Class در هسکل) به نتایج مشابهی رسیده‌اند.

سیستم تایپ هر دو به شدت قابل‌توسعه است. هر دو ایجاد تایپ‌های جدید، نام‌های مستعار و ترکیب تایپ‌های محصول (struct) با جمع (enum) را ساده کرده‌اند. تفاوت‌ها عمدتاً سطحی است: هسکل از یک کلمه کلیدی data برای هر دو استفاده می‌کند، در حالی که راست آن‌ها را تفکیک می‌کند.

جفت Option و Result برجسته‌ترین میراث این زبان است. مقایسه مستقیم نحوه تعریف آن‌ها در دو اکوسیستم نشان می‌دهد چگونه یک الگوی آکادمیک به استاندارد صنعت تبدیل شد:

-- Haskell
findUser :: Int -> Maybe User
findUser 0 = Nothing
findUser id = Just User { userId = id, userName = "Alice" }

-- Rust
fn find_user(id: u64) -> Option<User> {
    if id == 0 {
        None
    } else {
        Some(User { userId: id, userName: "Alice".to_string() })
    }
}

این الگو سریعاً در سوئیفت و اسکالا گسترش یافت. سوئیفت با معرفی Optional و سپس Result امنیت مدیریت خطا را در لایه کامپایلر نهادینه کرد. اسکالا با ادغام Option، Try و Either در کتابخانه استاندارد آن‌ها را به ابزارهای روزمره برنامه‌نویسی تبدیل کرد. امروز نوشتن کد در این زبان‌ها بدون در نظر گرفتن این الگوهای تابعی تقریباً غیرممکن است.

آینده برنامه‌نویسی؛ وقتی تئوری تبدیل به زیرساخت می‌شود

زبان‌هایی که دهه‌ها پیش در محافل دانشگاهی رد می‌شدند، امروز در لایه‌های زیربنایی اینترنت و سیستم‌های ابری ایستاده‌اند. حرکت صنعت به سمت معماری‌های تابعی نشان می‌دهد که ایمنی تایپ و شفافیت داده‌ها دیگر یک انتخاب لوکس نیستند، بلکه پیش‌نیاز مقیاس‌پذیری واقعی هستند. نسل بعدی ابزارها و فریم‌ورک‌ها احتمالاً نه با افزودن سینتکس‌های جدید، بلکه با عمق بخشیدن به همین اصول پایه‌ای شکل خواهند گرفت. زبانی که زمانی فقط برای اثبات قضایای ریاضی نوشته می‌شد، امروز الفبای پایداری نرم‌افزارهاست.