Разве "база данных фактов" не является основной особенностью miniKanren?
Я играл с miniKanren, пытаясь понять его, конвертируя в него очень простые учебные пособия по Prolog.
Обычно я использую Python, поэтому я начал с библиотеки LogPy, которая с тех пор была разветвлена и усовершенствована, поскольку на самом деле библиотека называется miniKanren.
Из примера, приведенного в README библиотеки, мы можем увидеть:
>>> from kanren import Relation, facts
>>> parent = Relation()
>>> facts(parent, ("Homer", "Bart"),
... ("Homer", "Lisa"),
... ("Abe", "Homer"))
>>> run(1, x, parent(x, "Bart"))
('Homer',)
Это тривиально соответствует тому, что вы могли увидеть в начале руководства по Prolog, например:
% facts.pl
parent(homer, bart).
parent(homer, lisa).
parent(abe, homer).
?- consult('facts')
true.
?- parent(X, bart).
X = homer
Я был доволен этим. Позже я обнаружил, что читаю все больше и больше литературы по MiniKanren (в общем смысле, а не библиотеки Python) и понял, что не видел ни одного примера, использующего базу данных фактов таким образом или упоминания о ней.
Я это пропустил? Или это на самом деле не особенность MiniKanren а-ля "Разумный интриган"?
Где я нашел такое, так это в Clojure core.logic
реализация, где есть это:
https://github.com/clojure/core.logic/wiki/Features
Он работает очень похожим образом, хотя и лучше, чем у Python, потому что db - это отдельный объект, а не глобальная переменная в библиотеке.
Python lib просто заимствовал идею, отличную от канрена, из core.logic
? Есть ли другие реализации MiniKanren, которые имеют что-то подобное? Или совсем другой подход?
1 ответ
Это отличный вопрос, и я думаю, что это отличный пример, который стоит иметь под рукой. Он поддерживается, но, возможно, не так четко и просто, как вы привыкли. Мы можем описать базу данных фактов на основе отношения за отношением в том же стиле, в котором вы ожидаете написать рекурсивное отношение Канрена. Я заимствую конкретный синтаксис изTRS 2/e
(defrel (parento f c)
(conde
((== f 'homer) (== c 'bart))
((== f 'homer) (== c 'lisa))
((== f 'abe) (== c 'homer))))
(defrel (stonecuttero p)
(conde
((== p 'abe))
((== p 'lenny))
((== p 'carl))
((== p 'glumplich))))
> (run* p (fresh (o) (stonecuttero p) (parento p o)))
(abe)
Если у вашего основного языка есть хорошая макросистема, вы, вероятно, могли бы написать ее кратко и развернуть до такой формы.
Это помогает?