По-перше, дозвольте мені похвалити вас за ваш прекрасний значок pw0n1e.
На це складний питання, на який слід відповісти, багато в чому тому, що існує так багато варіантів як miniKanren, так і Prolog. miniKanren і Prolog - це справді сімейства мов, що ускладнює порівняння їх особливостей або навіть того, як вони використовуються на практиці. Зважаючи на це, будь ласка, прийміть все, про що я говорю, з обережністю: якщо я скажу, що Prolog використовує пошук в глибині перших, майте на увазі, що багато реалізацій Prolog підтримують інші стратегії пошуку, і що альтернативні стратегії пошуку також можуть бути закодовані в мета -інтерпретаційний рівень. Тим не менш, miniKanren і Prolog мають різні філософії дизайну і роблять різні компроміси.
Prolog - одна з двох класичних мов для символічного програмування штучного інтелекту (інша класична мова - Lisp). Prolog досконалий у застосуванні символічних систем, заснованих на правилах, де декларативні знання кодуються логікою першого порядку. Мова оптимізована для виразності та ефективності для таких типів додатків, іноді за рахунок логічної чистоти. Наприклад, Prolog за замовчуванням не використовує "перевірку виникнення" в уніфікації. З точки зору математики / логіки, ця версія об'єднання є неправильною. Однак перевірка виникнення є дорогою, і в більшості випадків відсутність перевірки на виникнення не є проблемою. Це дуже прагматичне дизайнерське рішення, як і використання програми Prolog для пошуку в глибині перших і використання вирізання (!
) для управління зворотним трекінгу. Я впевнений, що ці рішення були абсолютно необхідні при роботі з обладнанням 1970-х років, і сьогодні вони дуже корисні при роботі над великими проблемами та при роботі з величезними (часто нескінченними!) Пошуковими просторами.
Prolog підтримує безліч "екстралогічних" або "нелогічних" функцій, включаючи вирізання assert
та retract
проекцію змінних для арифметики з використаннямis
, і так далі. Багато з цих функцій полегшують вираження складного потоку управління та маніпулювання глобальною базою фактів Prolog. Однією з дуже цікавих особливостей Prolog є те, що сам код Prolog зберігається у глобальній базі даних фактів, і його можна попросити під час виконання. Це змушує тривіально писати метаінтерпретатори, які змінюють поведінку коду Prolog під інтерпретацією. Наприклад, можна кодувати перший широту пошуку в Prolog за допомогою метаінтерпретатора, який змінює порядок пошуку. Це надзвичайно потужна техніка, яка недостатньо відома за межами світу Пролога. "Мистецтво Пролога" докладно описує цю техніку.
Величезні зусилля були спрямовані на вдосконалення впроваджень Prolog, більшість з яких базується на абстрактній машині Warren (WAM). WAM використовує побічну модель, в якій значення деструктивно присвоюються логічним змінним, при цьому ці побічні ефекти скасовуються під час зворотного відстеження. Багато функцій можна додати до Prolog, розширивши інструкції WAM. Одним із недоліків такого підходу є те, що документи про впровадження Prolog можуть бути важкими для читання без чіткого розуміння WAM. З іншого боку, у впровадника Prolog є спільна модель для обговорення проблем із впровадженням. Паралельно з Прологом було проведено велику кількість досліджень, кульмінацією якої стала Андора Пролог у 90-х роках. Принаймні, деякі з цих ідей живуть у провінції Ciao Prolog. (Ciao Prolog сповнений цікавих ідей, багато з яких виходять далеко за рамки стандарту Prolog.)
Prolog має прекрасний синтаксис "узгодження" шаблону на основі уніфікації, що призводить до дуже лаконічних програм. Прологери люблять свій синтаксис так само, як і Лісперс люблять свої s-вирази. У Prolog також є велика бібліотека стандартних предикатів. Завдяки всій техніці, яка переросла в WAM швидко, є дуже здібні та зрілі реалізації Prolog. Як результат, багато великих систем, заснованих на знаннях, були повністю написані в Prolog.
miniKanren був розроблений як мінімальна логічна мова програмування, з невеликою, легко зрозумілою і легко руйнується реалізацією. miniKanren спочатку був вбудований у схему та був перенесений на десятки інших мов хосту протягом останнього десятиліття. Найпопулярніша реалізація miniKanren - це 'core.logic' у Clojure, який тепер має багато розширень, подібних до Prolog, та низку оптимізацій. Останнім часом ядро реалізації miniKanren ще більше спростилося, в результаті чого крихітне "мікроядро" називається "microKanren". miniKanren може бути реалізований поверх цього ядра microKanren. Перенесення microKanren або miniKanren на нову мову хоста стало стандартною вправою для програмістів, які навчаються miniKanren. Як результат,
Стандартні реалізації miniKanren та microKanren не містять мутацій та інших побічних ефектів, за єдиним винятком: деякі версії miniKanren використовують рівність покажчика для порівняння логічних змінних. Я вважаю це "доброякісним ефектом", хоча багато реалізацій уникають навіть цього ефекту, передаючи лічильник через реалізацію. Також немає глобальної бази даних фактів. Філософія впровадження miniKanren натхненна функціональним програмуванням: мутації та ефектів слід уникати, а всі мовні конструкції повинні дотримуватися лексичної сфери. Якщо ви уважно подивитесь на реалізацію, ви можете навіть помітити пару монад. Реалізація пошуку заснована на поєднанні та маніпулюванні ледачими потоками, знову ж таки без використання мутації. Такі варіанти впровадження призводять до зовсім інших компромісів, ніж у Prolog. У Prolog змінний пошук - це постійний час, але зворотне відстеження вимагає скасування побічних ефектів. У miniKanren змінний пошук дорожчий, але зворотній трек "безкоштовний". Насправді, у miniKanren немає зворотнього огляду, завдяки тому, як обробляються потоки.
Одним із цікавих аспектів реалізації miniKanren є те, що код за своєю суттю є безпечним для потоків та --- принаймні теоретично, - тривіально паралелізованим. Звичайно, паралелізація коду, не роблячи його повільніше , не є тривіальною, враховуючи, що кожному потоку чи процесу потрібно надати достатньо роботи, щоб компенсувати накладні витрати на паралелізацію. І все-таки це сфера впровадження miniKanren, яка, сподіваюся, отримає більше уваги та експериментів.
miniKanren використовує перевірку виникнення для об'єднання і використовує повний переплетений пошук замість першого глибинного пошуку. Пошук з перемежуванням використовує більше пам’яті, ніж перший на глибині пошуку, але може знайти відповіді в деяких випадках, коли пошук на глибині першого буде назавжди розходитися / циклічно. miniKanren робить підтримку кілька екстра-логічні оператори --- conda
, condu
і project
, наприклад. conda
і condu
може бути використаний для імітації розрізу Prolog і project
може бути використаний для отримання значення, пов'язаного з логічною змінною.
Наявність conda
, condu
іproject
--- і можливість легко змінювати стратегію пошуку --- дозволяє програмістам використовувати miniKanren як вбудовану мову, що нагадує пролог. Особливо це стосується користувачів 'core.logic' Clojure, що включає безліч розширень, подібних до Prolog. Це "прагматичне" використання miniKanren, здається, пояснює більшість використання miniKanren у промисловості. Програмісти, які хочуть додати систему міркувань на основі знань до існуючої програми, написаної на Clojure або Python або JavaScript, як правило, не зацікавлені переписувати всю свою програму в Prolog. Вставлення невеликої мови логічного програмування в Clojure або Python набагато привабливіше. Вбудована реалізація Prolog працювала б так само добре для цієї мети, імовірно.
Окрім використання miniKanren як прагматичної вбудованої логічної мови програмування, подібної за духом до Prolog, miniKanren використовується для досліджень у "реляційному" програмуванні. Тобто при написанні програм, які ведуть себе як математичні відносини, а не математичні функції. Наприклад, у схемі append
функція може додавати два списки, повертаючи новий список: виклик функції (append '(a b c) '(d e))
повертає список (a b c d e)
. Однак ми можемо також трактувати append
як відношення у трьох місцях, а не як функції двох аргументів. Потім виклик (appendo '(a b c) '(d e) Z)
асоціює змінну логіки Z
зі списком (a b c d e)
. Звичайно, речі стають цікавішими, коли ми розміщуємо логічні змінні в інших позиціях. Виклик (appendo X '(d e) '(a b c d e))
пов'язується X
з (a b c)
, під час дзвінка(appendo X Y '(a b c d e))
асоційовані X
і Y
з парами списків, які при додаванні дорівнюють (a b c d e)
. Наприклад X
= (a b)
і Y
= (c d e)
є одна така пара значень. Ми також можемо написати (appendo X Y Z)
, що буде виробляти нескінченно багато трійок списків X
, Y
і Z
таким чином, що додавання X
до Y
виробляють Z
.
Ця реляційна версія append
може бути легко виражена в Prolog, і вона дійсно показана у багатьох навчальних посібниках. На практиці більш складні програми Prolog, як правило, використовують принаймні декілька поза логічних можливостей, таких як вирізання, які гальмують можливість трактувати отриману програму як відношення. Навпаки, miniKanren явно призначений для підтримки цього стилю реляційного програмування. Пізніші версії miniKanren має підтримку рішення символічного обмежень ( symbolo
, numbero
,absento
, обмеження нерівності, номінальне логічне програмування) для полегшення запису нетривіальних програм як відносин. На практиці я ніколи не використовую жодної екстралогічної функції miniKanren, і всі свої програми miniKanren я пишу як відносини. Найцікавіші реляційні програми - це реляційні перекладачі для підмножини Схеми. Ці інтерпретатори мають багато цікавих здібностей, наприклад, генеруючи мільйон (I love you)
схемних програм, які оцінюються до списку , або тривіально генерують лайки (програми, які оцінюють самі).
miniKanren робить ряд компромісів, щоб дозволити цей стиль реляції програмування, який сильно відрізняється від компромісів, які робить Prolog. З часом miniKanren додав більше символічних обмежень, ставши справді символічно орієнтованою логікою програмування обмежень. У багатьох випадках ці символічні обмеження дозволяють уникнути використання поза логічних операторів, таких як condu
і project
. В інших випадках цих символічних обмежень недостатньо. Краща підтримка символічних обмежень є одним із активних напрямків дослідження miniKanren разом із більш широким питанням про те, як писати більші та складніші програми як відносини.
Коротше кажучи, і miniKanren, і Prolog мають цікаві функції, реалізацію та використання, і я думаю, що варто вивчити ідеї з обох мов. Є й інші дуже цікаві мови логічного програмування, такі як Меркурій, Керрі та Гьодель, кожна з яких має власне прийняття логічного програмування.
Я закінчу кількома ресурсами miniKanren:
Основний веб-сайт miniKanren:
http://minikanren.org/
Інтерв'ю, яке я дав про реляційне програмування та miniKanren, включаючи порівняння з Prolog:
http://www.infoq.com/interviews/byrd-relational-programming-minikanren
Ура,
- Буде