Мрія про декларативне програмування [закрито]


26

Чому не здійснилася мрія про декларативне програмування? Які конкретні перешкоди стають на шляху? Напростий приклад, чому я не можу сказати

sort(A) is defined by sort(A) in perm(A) && asc(sort(A))

і автоматично отримувати з нього алгоритм сортування. permозначає перестановки та ascзасоби висхідної.


4
До речі ваш конкретний приклад роду вже доступні: gkoberger.github.io/stacksort
Den

3
Ви чули про Пролог? Просто шукайте "Програмування набору відповідей". Існує багато систем, побудованих за логікою за замовчуванням.
шлінгель

16
Ну, на це питання легко відповісти. Спроба впровадити таку систему . Що заважало тобі це робити успішно? Шанси добре, що все, що зупинило вас, зупинило всіх інших.
Ерік Ліпперт

4
Мені спокушається вважати, що це питання заслуговує на більше кредиту, ніж воно отримує. Коли ви подивитесь на це з першого погляду, ви можете подумати: Ну, це просто! Ви повинні запрограмувати всю цю логіку за нею, а комп'ютери просто не такі розумні. ... Але потім ви повертаєтесь і погляньте на це питання, і ще раз подумаєте, ну так, це просто, і вам потрібно запрограмувати всю цю логіку - і комп'ютери не обов'язково є найгострішими інструментами в сараї, правда - але в цьому поясненні є набагато більше глибини, ніж те, що просто лежить на поверхні.
Panzercrisis

3
Ваш опис алгоритму сортування є декларативним, так, але це впевнено, оскільки пекло не є ефективним. Існують n!перестановки послідовності, і в гіршому випадку ваш алгоритм повинен буде спробувати їх усіх, щоб знайти відсортовану. Факторний час приблизно такий же поганий, як і алгоритм для обробки послідовності.
Бенджамін Ходжсон

Відповіді:


8

Є кілька дуже хороших відповідей. Я спробую внести свій внесок у дискусію.

На тему декларативного, логічного програмування в Пролозі виходить чудова книга Річарда О'Кіф "Ремесло Пролога" . Йдеться про написання ефективних програм за допомогою мови програмування, яка дозволяє писати дуже неефективні програми. У цій книзі, обговорюючи ефективні реалізації декількох алгоритмів (у розділі "Методи програмування"), автор застосовує такий підхід:

  • визначте проблему англійською мовою
  • написати робоче рішення, яке є максимально декларативним; зазвичай це означає саме те, що ви маєте у своєму питанні, просто виправте Пролог
  • звідти вживайте заходів, щоб удосконалити реалізацію, щоб зробити її швидшою

Найяскравіше (для мене) спостереження, яке я зміг зробити під час роботи над цим:

Так, остаточна версія реалізації набагато ефективніша, ніж "декларативна" специфікація, з якої розпочався автор. Це все ще дуже декларативно, лаконічно і легко зрозуміти. Між тим, що сталося між ними, це те, що остаточне рішення фіксує властивості проблеми, про яку початкове рішення не було в курсі.

Іншими словами, впроваджуючи рішення, ми використали якомога більше наших знань про проблему. Порівняйте:

Знайдіть перестановку списку таким чином, щоб усі елементи знаходились у порядку зростання

до:

Об'єднання двох відсортованих списків призведе до відсортованого списку. Оскільки можуть бути вже відсортовані підсписи, використовуйте їх як вихідну точку замість списків довжиною 1.

Невелика сторона: таке визначення, як те, що ви дали, є привабливим, оскільки воно дуже загальне. Однак я не можу уникнути відчуття, що цілеспрямовано ігнорує той факт, що перестановки є, ну, комбінаторною проблемою. Це те, що ми вже знаємо ! Це не критика, а лише спостереження.

Щодо справжнього питання: як рухатись вперед? Ну, один із способів - дати якомога більше знань про проблему, яку ми декларуємо на комп’ютері.

Найкраща мені спроба реально вирішити проблему представлена ​​в книгах Олександра Степанова в співавторстві «Елементи програмування» та «Від математики до загального програмування» . Мені, на жаль, не підходить підсумовувати (або навіть повністю розуміти) все, що є в цих книгах. Однак підхід існує для визначення ефективних (або навіть оптимальних) бібліотечних алгоритмів та структур даних, за умови, що всі відповідні властивості вводу відомі заздалегідь. Кінцевий результат:

  • Кожна чітко визначена трансформація - це уточнення обмежень, які вже існують (властивості, які відомі);
  • Ми дозволяємо комп'ютеру вирішити, яке перетворення оптимальне виходячи з існуючих обмежень.

Що стосується того, чому це ще не зовсім сталося, ну, інформатика - це справді молода сфера, і ми все ще справляємося з по-справжньому цінуючи новизну більшості.

PS

Щоб дати вам смак того, що я маю на увазі під «вдосконаленням реалізації»: візьміть, наприклад, просту проблему отримання останнього елемента списку, в Prolog. Канонічне декларативне рішення полягає в тому, щоб сказати:

last(List, Last) :-
    append(_, [Last], List).

Тут декларативне значення append/3:

List1AndList2є конкатенація List1іList2

Оскільки у другому аргументі у append/3нас є список лише з одним елементом, а перший аргумент ігнорується (підкреслення), ми отримуємо розкол вихідного списку, який відкидає передню частину списку ( List1у контексті append/3) та вимагає зворотна List2частина ( в контексті append/3) - це справді список із лише одним елементом: значить, це останній елемент.

Фактична реалізація забезпечується SWI-Prolog , однак, каже:

last([X|Xs], Last) :-
    last_(Xs, X, Last).

last_([], Last, Last).
last_([X|Xs], _, Last) :-
    last_(Xs, X, Last).

Це все ще гарно декларативно. Прочитайте зверху донизу, там написано:

Останній елемент списку має сенс лише для переліку щонайменше одного елемента. Останнім елементом пари хвоста та головки списку є: голова, коли хвіст порожній, або останній із непустого хвоста.

Причиною, по якій надається така реалізація, є обхід практичних питань, пов'язаних із моделлю виконання Prolog. В ідеалі він не повинен змінювати, яка реалізація використовується. Так само ми могли б сказати:

last(List, Last) :-
    reverse(List, [Last|_]).

Останній елемент списку - це перший елемент зворотного списку.

Якщо ви хочете отримати непереконливу дискусію про те, що добре, декларативний Prolog, просто перегляньте деякі питання та відповіді в тезі Prolog на стеку Overflow .


2
+1 - показує, як декларативний дизайн може перейти від простої абстракції до більш конкретної реалізації за допомогою ітеративного процесу проектування.
йогобрюс

1
@Boris Це хороша відповідь. Ця книга сидить на моїй книжковій полиці. Напевно, саме час я відкрив це.
davidk01

1
@ davidk01 Одна з кращих книг там. Це передбачає, що вам досить зручно з Prolog і програмуванням в цілому, але підхід, який він вимагає до програмування, є і прагматичним, і дуже ретельним.
XXX

2
@Boris Я знаю, що приклад не є складним, але вирішальне значення має продуктивність ітеративного дизайнерського процесу - реальної сили декларативних мов - і це дуже практичне значення. Декларативні мови пропонують чіткий, послідовний, рекурсивний підхід до ітеративного вдосконалення. Імперативні мови цього не роблять.
йогобрюс

1
+1 за "отримайте ваші результати непереконливих дискусій про те, що добре, декларативний пролог" ... дуже правда, що ми, як правило, не погоджуємось!
Даніель Ліонс

50

Логічні мови вже роблять це. Ви можете визначити сортування аналогічно тому, як ви це робите.

Основна проблема - продуктивність. Комп'ютери можуть бути чудовими в обчисленні багатьох речей, але вони по суті німі. Кожне "розумне" рішення, яке може прийняти комп'ютер, програмувало в нього програміст. І це рішення зазвичай описується не тим, як виглядає кінцевий результат, а тим, як досягти, крок за кроком, цього кінцевого результату.

Уявіть історію про Голема . Якщо ви спробуєте дати йому абстрактну команду, то в кращому випадку він зробить це неефективно і в гіршому випадку завдасть шкоди собі, вам чи комусь іншому. Але якщо ви опишите те, що хочете, якомога детальніше, ви гарантуєте, що завдання буде виконано ефективно та ефективно.

Завдання програміста вирішувати, який рівень абстракції використовувати. За додаток, яке ви робите, збираєтесь вийти на високий рівень і описати його абстрактним чином і приймати хіт продуктивності або знизитись та забруднити, витратити на це в 10 разів більше часу, але отримаєте алгоритм, який на 1000 разів ефективніший?


6
Це може допомогти дізнатися, що слово Golem גולם насправді означає "сировина", тобто найосновніший стан, в якому може знаходитися машина / сутність.
dotancohen

2
Декларативні мови по суті не є перешкодою для зниження рівнів абстракції. І Haskell, і Standard ML, по-різному, дозволяють робити прості декларативні висловлювання про типи / функції в одному місці, надають діапазон конкретних та конкретних реалізацій функцій в окремому місці та способи співставлення типів з реалізаціями в іншому. Тим часом, найкраща практика OO / Imperative languages ​​зараз дуже стосується початку високого / простого, а потім додавання деталей щодо впровадження. Різниця полягає в тому, що висока абстракція легша у FP, низький рівень легше в обов'язковому порядку.
йогобрюс

2
Слід сказати, що також можна в будь-якій згаданій мові вирішити вибір конкретної реалізації автоматично на основі властивостей типу, а не жорсткого кодування конкретних збігів, що в значній мірі забезпечує те, що хоче ОП. У Haskell класи типів були б ключовим інструментом для цього. У стандартному ML, функтори.
йогобрюс

22
@BAR Golem! = Golum Golem є з єврейського фольклору
Ейфорія

10
Мій відхід від цієї відповіді - це написати на своєму ноутбуці א laptopת.
Dan J

45

На додаток до чудового моменту Euphoric , я хотів би додати, що ми вже використовуємо декларативні мови в багатьох місцях, де вони працюють добре, тобто описують стан, який, мабуть, не зміниться або запитає те, для чого комп'ютер насправді може генерувати ефективний код самостійно:

  • HTML оголошує, який вміст веб-сторінки.

  • CSS оголошує, як мають виглядати різні типи елементів на веб-сторінці.

  • Кожна реляційна база даних має мову визначення даних, яка декларує структуру бази даних.

  • SQL набагато ближче до декларативного, ніж імперативного, оскільки ви розповідаєте, що ви хочете бачити, і планувальник запитів бази даних з'ясовує, як насправді це зробити.

  • Можна стверджувати, що більшість файлів конфігурації (.vimrc, .profile, .bashrc, .gitconfig) використовують мову, що залежить від домену, яка значною мірою є декларативною.


3
Я згадаю GNU Make, XSLT, Angular.js як широко використовувані речі, які також є декларативними (хоча кутовий, можливо, трохи підштовхує визначення).
Марк К Коуан

Дозвольте додати до цього списку регулярні вирази.
Шверн

7
Люди, як правило, забувають, що декларативні мови є загальними . Вони просто не використовують цілі мови. Додайте регулярний вираз до цього списку.
slebetman

Трохи педантично, але все-таки: не кожна база даних має DDL, просто подумайте про величезну кількість безсхемових баз даних NoSQL. Кожна реляційна база даних може мати, але не кожна база даних.
Відновіть Моніку - Дірк

1
@dirkk Не думав про це. Виправив мою відповідь.
Іксрек

17

Абстракції є герметичними

Ви можете реалізувати декларативну систему, де ви заявляєте, що хочете, а упорядник чи тлумач визначає порядок виконання. Теоретична перевага полягає в тому, що це звільняє вас від думки про "як", і вам не потрібно деталізувати цю реалізацію. Однак на практиці для загальних обчислень потрібно все-таки думати про "як" і писати всілякі хитрощі, маючи на увазі, як це буде реалізовано, оскільки в іншому випадку компілятор може (і часто буде) обирати реалізацію, яка буде дуже, дуже, дуже повільно (наприклад, n! операцій, де n вистачить).

У вашому конкретному прикладі, ви отримаєте A алгоритму сортування - це не означає , що ви отримаєте хороший або навіть кілька корисних один. Ваша задана дефініція, якщо вона буде реалізована буквально (як це можливо), призводить до http://en.wikipedia.org/wiki/Bogosort, яка непридатна для великих наборів даних - це технічно правильно, але їй потрібно вічність, щоб сортувати тисячу чисел .

Для деяких обмежених доменів ви можете написати системи, які майже завжди добре допомагають з'ясувати хорошу реалізацію, наприклад, SQL. Для обчислень загального призначення, які не працюють особливо добре - ви можете записувати системи в, скажімо, Prolog, але ви повинні візуалізувати, як саме ваші декларації будуть зрештою перетворені на імперативне замовлення виконання, і це втратить велику частину очікуваного декларативного переваги програмування.


Хоча те, що ви говорите, по суті вірно, погана робота не є ознакою протікання абстракції, якщо інтерфейс / контракт не дає вам гарантій, наприклад, про час виконання.
Валентина

3
Пітерс не каже, що погані показники є ознакою нещільної абстракції, @valenterry. Якщо що-небудь, він говорить протилежне: щоби досягти хороших показників, деталі впровадження змушені просочуватися.
йогобрюс

2
Я думаю, що оманливо говорити, що абстракції є витоковими лише тому, що вам потрібно зрозуміти впровадження, щоб зрозуміти, як це впливає на ефективність. Мета абстракції - не захищати вас від необхідності думати про ефективність.
Доваль

1
@jamesqf У декларативному програмуванні ви просто заявите, що щось відсортовано. Ви можете оголосити порядок сортування прив'язаним до певної змінної / властивості. І тоді було б так. Не потрібно чітко називати сортування кожного разу, коли додаються нові дані або змінюється порядок сортування.
Гайда

1
@jamesqf Ви справді не можете зрозуміти сенс, не намагаючись самостійно (я б рекомендував QML з Qt для гри з декларативними ідеями). Уявіть собі когось, хто знає лише імперативне програмування, і вони намагаються зрозуміти точку OOP або функціонального програмування, не намагаючись насправді реально.
Гайда

11

Обчислювальна здатність - це найважливіша причина, чому декларативне програмування не виявилося таким простим, як здається.

Багато проблем, які досить легко констатувати, виявилися невирішеними або мають складну комплексну проблему для вирішення. Це часто трапляється, коли ми враховуємо негативні класи та класифікацію, підрахунковість та рекурсію.

Я хотів би пояснити це деякими доменами, які добре відомі.

Рішення про те, який клас CSS використовувати, потребує знання та врахування всіх правил CSS. Додавання нових правил може визнати недійсними всі інші рішення. Негативні класи CSS навмисно не додаються до мови через неповні проблеми, але відсутність негативних класів ускладнює дизайнерські рішення CSS.

У оптимізаторі запитів (SQL) існує непросте завдання вирішити, в якому порядку приєднатися, які індекси використовувати та яку пам'ять виділити тимчасовим результатам. Це відома NP-повна проблема і ускладнює розробку баз даних та формулювання запитів. Щоб сформулювати це по-іншому: розробляючи базу даних або запит, дизайнеру необхідно знати дії та порядок дій, які, скоріш за все, здійснює оптимізатор запитів. Досвідченому інженеру потрібні знання евристики, що використовується великими постачальниками баз даних.

Файли конфігурації декларативні, але певні конфігурації важко оголосити. Наприклад, для правильної настройки функцій потрібно враховувати версії, розгортання (та історію розгортання), можливі зміни вручну та можливі конфлікти з іншими налаштуваннями. Правильна перевірка конфігурації може стати проблемою, що не стосується NP.

Результат полягає в тому, що ці ускладнення сприймають початківців несподівано, вони порушують «красу» декларативного програмування і змушують деяких інженерів шукати інші рішення. Міграція недосвідчених інженерів із SQL в NoSQL могла бути спровокована основними складностями реляційних баз даних.


2
"Негативні класи CSS навмисно не додаються до мови через проблеми, що не стосуються NP".
Іван Дворак

Це трохи вправа, але з негативними селекторами CSS можна переписати їх на проблему 3SAT (з останньою статтею DOM), що вимагає спробувати всі можливі комбінації, щоб побачити, чи збігається вона.
Діббеке

1
Невелике доповнення. У CSS 3 та 4 дозволені негативні селектори, але: не псевдокласи можуть бути вкладені.
Діббеке

2

Ми маємо різницю в декларативності мов програмування, яка корисно використовується для перевірки цифрової логіки.

Зазвичай цифрова логіка описується на рівні передачі регістра (RTL), де визначається логічний рівень сигналів між регістрами. Щоб перевірити, чи ми все більше додаємо властивості, визначені більш абстрактно та декларативно.

Однією з декларативних мов / підмножин мови називається PSL для мови властивостей властивостей. При тестуванні RTL-моделі множника, в якій, наприклад, потрібно вказати всі логічні операції зсуву та додавання протягом декількох тактових циклів; ви можете записати властивість в образі assert that when enable is high, this output will equal the multiplication of these two inputs after no more than 8 clock cycles. Опис PSL може потім перевірятися разом з RTL в рамках моделювання, або PSL може бути офіційно доведено, що він відповідає опису RTL.

Більш декларативна модель PSL змушує описати таку ж поведінку, що й опис RTL, але досить іншим способом, який можна автоматично перевірити проти RTL, щоб побачити, чи вони згодні.


1

Переважно проблема полягає в тому, як ви моделюєте дані; і декларативне програмування тут не допомагає. Імперативними мовами у вас вже є багато бібліотек, які роблять для вас багато матеріалів, тому вам потрібно лише знати, як зателефонувати. Особливо можна розглянути це декларативне програмування (мабуть, найкращий приклад для цього - Stream API на Java 8 ). Маючи це, абстракція вже вирішена, а декларативне програмування не потрібне.

Крім того, як було сказано, мови логічного програмування вже роблять саме те, що ви хочете. Можна сказати, що проблема полягає в продуктивності, але з сьогоднішнім обладнанням та дослідженнями в цій галузі все можна покращити, щоб бути готовим до використання у виробництві; насправді Prolog використовується для ШІ, але я вірю лише академіям.

Слід зазначити, що він застосовується для мов програмування загального призначення. Для доменних мов декларативні мови значно кращі; SQL, мабуть, найкращий приклад.


3
Моделювання даних? Ви вибрали те, що найгірше в імперативах. Декларативні функціональні мови, такі як Haskell та ML, досконалі при моделюванні даних. Наприклад, алгебраїчні типи даних та рекурсивні типи даних зазвичай можуть бути визначені всебічно в одному або двох рядках. Звичайно, у вас все ще є функції запису, але їх код невблаганно випливає з визначення типу і обмежується ним. Химерне порівняння зробити.
йогобрюс

1
@itsbruce Найбільше реальних даних не легко відобразити в ADT; подумайте, як працює більшість баз даних. Як пролог - Ерланг, ви праві, вони різні мови. Я згадав, що одна функціональна, а інша - логічна, але найкраще, якщо я видалю ціле порівняння.
m3th0dman

1
@ m3th0dman База даних - це лише багато кортежів / записів. Haskell трохи каліка там, тому що йому не вистачає записів, але в них є кортежі, і ML має і те, і інше. І у випадку Haskell кількість таблички, необхідної для оголошення нового типу даних псевдозапису, все ще набагато менша, ніж потрібно для створення штучної структури на середній мові OOP, статично набраної. Чи можете ви детальніше розповісти про те, як більшість даних легко не відображається в ADT?
Довал

1
@ m3th0dman Ах, ось чому схеми баз даних визначені в обов'язковій мові, добре підходить до завдання. О, ні, це були б декларативні DDL. Насправді загальний процес моделювання даних має відношення до програми, яка буде працювати з нею, потоків даних та структур, а не мови, що реалізує додаток. Іноді вони спотворюються, щоб відповідати особливостям OO мови та те, що підтримує її ORM, але зазвичай це погано, а не особливість. Декларативні мови краще підходять для вираження концептуальної / логічної моделі даних.
йогобрюс

1
@itsbruce Я не говорив, що парадигма процедур краща за декларативну при визначенні даних; Я говорив, що декларативна парадигма не краща (ні гірша), ніж процедурна (для мов загального призначення). Щодо маніпулювання даними, декларативної частини SQL недостатньо для реальних програм; інакше ніхто не придумав би і не скористався процедурними розширеннями. Щодо статті, я не погоджуюся з нею з реферату, де вона суперечить Бруксу; він будував свої ідеї з реальних проектів, поки ці хлопці не створили нічого видатного, щоб довести свою теорію.
m3th0dman

0

Це виглядатиме приблизно так .. {(що-небудь => читати файл і викликати URL) | зателефонуйте за URL-адресою та прочитайте файл} Однак це виконання, і стан системи в результаті змінюється, але це не очевидно з джерела.

Декларації можуть описати машину з кінцевим станом та її переходи. FSM - це як протилежність декларацій без дій, навіть якщо єдиною дією є зміна стану на наступний стан.

Перевага використання цього методу полягає в тому, що переходи та дії можуть бути визначені предикатами, які застосовуються до декількох переходів, а не лише до одного.

Я знаю, що це звучить трохи дивно, але в 2008 році я написав генератор програм, який використовує цей метод, і сформований C ++ в 2–15 разів більше, ніж джерело. Зараз у мене понад 75 000 рядків C ++ з 20 000 рядків введення. З цим ідуть дві речі: послідовність і повнота.

Послідовність: Жоден два предикати, які можуть бути істинними одночасно, не можуть означати непослідовних дій, як і x = 8, і x = 9, ні різні наступні стани.

Повнота: Логіка кожного переходу стану задана. Це може бути важко перевірити для систем з N підзаголовок із станами> 2 ** N, але є цікаві комбінаторні методи, які можуть все перевірити. У 1962 році я написав фазу 1 сортування системи для машин 7070, використовуючи цей тип генерації умовного коду та комбінаторну налагодження. З 8000 рядків у своєму роді кількість помилок з дня першого випуску назавжди дорівнювала нулю!

Друга фаза, 12000 рядків, мала понад 60 помилок за перші два місяці. Про це можна сказати набагато більше, але це працює. Якби виробники автомобілів використовували цей метод для перевірки прошивки, ми не побачили б збоїв, які ми бачимо зараз.


1
Це дійсно не відповідає на початкове запитання. Як фактор послідовності та повноти впливає на те, що більшість програмувань все ще є процедурними, а не деклараційними?
Джей Елстон

Здається, ваш вступний параграф є відповіддю до пункту відповіді програмістів arnaud.stackexchange.com/a/275839/67057 , а не до самого питання. Це має бути коментар там (на моєму екрані ваша відповідь вже не нижче його, з одного боку). Я думаю, що решта вашої відповіді є ілюстрацією того, як невелика кількість декларативного коду могла б генерувати велику кількість еквівалентного імперативного коду, але це не ясно. Ваша відповідь потребує певного пристосування, особливо щодо важливих моментів.
йогобрюс

-3

Не все можна представити декларативно.

Часто ви точно хочете контролювати хід виконання

Наприклад, наступний псевдо-код: if whatever read a file call an URL else call an URL write a file Як би ви це декларативно представляли?

Звичайно, є, мабуть, деякі екзотичні способи зробити це. Як монади . Але вони, як правило, більш громіздкі, складні та набагато менш інтуїтивні, ніж їхня процесуальна частина.

Все зводиться до того, що "взаємодія" з вашим оточенням / системою не є декларативним. Все, що стосується вводу-виводу, є по суті процедурним. Ви повинні точно сказати, коли і що повинно відбутися, і в якому порядку.

Декларатив чудово підходить для всього, що суто пов'язане з обчисленням. Як гігантська функція, ви ставите X і отримуєте Y. Це чудово. Прикладом цього є HTML, введення - текст, вихід - те, що ви бачите у своєму браузері.


2
Я цього не купую. Чому ваш приклад не є декларативним? Це if/ elseв такому випадку як виглядатиме декларативна альтернатива? Це, звичайно, не read/ write/ callчастини, оскільки вони приємні декларативні списки значень (якщо ви маєте на увазі, що вони загорнуті {...; ...}, чому б не мати на увазі, що вони вкладені [..., ...]?) Звичайно, список - це просто безкоштовні моноїди; багато інших теж зробили б. Я не бачу, чому монади тут доречні; вони просто API. Haskell пішов з потоків -> монадів, щоб допомогти скласти вручну, але логічні мови можуть складати списки в порядку автоматично.
Варбо

2
-1 тільки для Монадів. 1. Вони насправді не екзотика (списки та набори - це монади, і всі ними користуються). 2. Вони не мають нічого спільного з примушуючи , що потрібно зробити в певній послідовності (Haskell робити нотації виглядають імперативне , але це не так ). Декларативні / функціональні мови визначають зв’язки та залежності. Якщо функція X потребує введення Y, Y буде генеруватися перед X. Визначте залежності залежно і правильна послідовність подій визначить себе. Велике взаємодія подія руху, а не в одній заданій послідовності. Декларативні мови не ускладнюють реагування на події.
йогобрюс

Лінь дещо ускладнює це, але лінь не є частиною визначення декларативних мов, більшість з яких не використовують її. А для тих, хто це робить, спосіб гарантувати оцінку не має нічого спільного з монадами. Для прикладу, коли декларативна мова використовується виключно для взаємодії, а не абстрактних обчислень, не вказує порядок, але робить чорт упевненим, що правильні речі відбуваються послідовно, дивіться не далі, ніж Puppet DSL. Котрий бонус у тому, що трапляються лише необхідні речі - не те, що загальномовні мови полегшують.
йогобрюс

1
На додаток до @itsbruce, реактивне програмування вважається декларативним і стосується взаємодії із середовищем.
Maciej Piechotka
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.