Нечисті мови насправді не відрізняються від більш звичних імперативних мов, особливо зараз, коли було скопійовано багато функціональних хитрощів. Що відрізняється від стилю - як ви вирішуєте проблеми.
Незалежно від того, чи вважаєте ви Haskell чистим чи вважаєте монад IO як домішкою, стиль Haskell є крайньою формою цього стилю і варто цього вивчити.
Монада Haskell IO виведена з математичної теорії (звичайно) монад. Однак для імперативних програмістів я думаю, що зворотний спосіб приходу до монад має більше сенсу.
Перша фаза - чиста функціональна мова може легко повернути велике значення рядка як результат. Ця велика рядок може бути вихідним кодом імперативної програми, виведеною чисто функціональним шляхом з деяких параметрів, що визначають вимоги. Потім ви можете створити компілятор "вищого рівня", який запускає ваш генератор коду, а потім автоматично подає згенерований код в імперативний компілятор мови.
Фаза друга - замість генерування текстового вихідного коду ви генеруєте сильно набране дерево абстрактного синтаксису. Ваш обов'язковий компілятор мови поглинається у ваш компілятор "вищого рівня" та приймає AST безпосередньо як вихідний код. Це набагато ближче до того, що робить Haskell.
Це все ще незручно. Наприклад, у вас є два різних види функцій - ті, які оцінювались на етапі генерації коду, і ті, які виконуються під час запуску створеної програми. Це трохи схоже на відмінність між функціями та шаблонами в C ++.
Отже, для фази 3 зробіть обидві однаковими - однакова функція з тим самим синтаксисом може бути частково оцінена під час "генерації коду", або повністю оцінена, або взагалі не оцінена. Крім того, відмовтеся від усіх циклічних конструкцій AST-вузлів на користь рекурсії. Насправді відмовтеся від ідеї вузлів AST як особливого виду даних взагалі - не маєте «буквального значення» вузлів AST, просто маєте значення тощо.
Це в значній мірі те, що робить монада IO - оператор зв'язування - це спосіб складання "дій" для формування програм. Це нічого особливого - лише функція. Багато виразів і функцій можуть бути оцінені під час "генерації коду", але ті, які залежать від побічних ефектів вводу / виводу, повинні мати затримку оцінки до часу виконання - не за яким-небудь спеціальним правилом, а як природний наслідок залежності даних у вирази.
Взагалі монади - це просто узагальнення - вони мають однаковий інтерфейс, але реалізують абстрактні операції по-різному, тому замість того, щоб оцінювати опис імперативного коду, вони оцінюють щось інше. Маючи той самий інтерфейс, це означає, що ви можете зробити монадам деякі речі, не піклуючись про монаду, що виявляється корисним.
Цей опис, без сумніву, змусить голови пуристів вибухати, але мені це пояснює деякі реальні причини, чому Хаскелл цікавий. Це розмиває межу між програмуванням та метапрограмуванням та використовує інструменти функціонального програмування для винахідництва імперативного програмування, не потребуючи спеціального синтаксису.
Критика, яку я маю щодо шаблонів C ++, полягає в тому, що вони є своєрідним розбитим чистим функціональним підмовою на імперативній мові - щоб оцінити ту саму основну функцію під час компіляції, а не під час виконання, вам доведеться повторно реалізовувати її за допомогою зовсім іншого стилю кодування. У Хаскеллі, хоча домішки повинні бути позначені як такі у своєму типі, точно таку ж функцію можна оцінювати як у сенсі метапрограмування, так і в сенсі немета програмування під час виконання в тій же програмі - немає жорсткої лінії між програмуванням та метапрограмуванням.
Однак, є деякі метапрограмування, які стандартний Haskell не може зробити, в основному тому, що типи (а може бути і кілька інших речей) не є першокласними значеннями. Однак є мовні варіанти, які намагаються вирішити це питання.
Багато речей, про які я говорив про Haskell, можна застосувати в нечистих функціональних мовах - а іноді навіть в імперативних мовах. Haskell відрізняється тим, що у вас немає іншого вибору, окрім як прийняти такий підхід - це в основному змушує вас навчитися цьому стилю роботи. Ви можете "написати C в ML", але ви не можете "написати C в Haskell" - принаймні, не дізнавшись, що відбувається під кришкою.