Tout d'abord, permettez-moi de vous féliciter pour votre belle icône pw0n1e.
C'est une question délicate à répondre, en grande partie parce qu'il existe de nombreuses variantes de miniKanren et Prolog. miniKanren et Prolog sont vraiment des familles de langues, ce qui rend difficile la comparaison de leurs caractéristiques, voire de leur utilisation dans la pratique. Pour cette raison, veuillez prendre tout ce que je suis sur le point de dire avec prudence: si je dis que Prolog utilise la recherche en profondeur d'abord, sachez que de nombreuses implémentations de Prolog prennent en charge d'autres stratégies de recherche, et que des stratégies de recherche alternatives peuvent également être encodées à la méta -niveau de l'interprète. Pourtant, miniKanren et Prolog ont des philosophies de conception différentes et font des compromis différents.
Prolog est l'un des deux langages classiques de programmation en intelligence artificielle symbolique (l'autre langage classique étant Lisp). Prolog excelle dans la mise en œuvre de systèmes basés sur des règles symboliques dans lesquels la connaissance déclarative est codée en logique du premier ordre. Le langage est optimisé pour l'expressivité et l'efficacité pour ces types d'applications, parfois au détriment de la pureté logique. Par exemple, par défaut, Prolog n'utilise pas le "contrôle d'occurrence" dans l'unification. D'un point de vue mathématique / logique, cette version de l'unification est incorrecte. Cependant, la vérification des événements est coûteuse et, dans la plupart des cas, l'absence de vérification des événements n'est pas un problème. Il s'agit d'une décision de conception très pragmatique, tout comme l'utilisation par Prolog de la recherche en profondeur d'abord et l'utilisation de la coupe (!
) pour contrôler le retour en arrière. Je suis sûr que ces décisions étaient absolument nécessaires lors de l'exécution sur le matériel des années 1970, et sont aujourd'hui très utiles pour travailler sur de gros problèmes et pour gérer d'énormes espaces de recherche (souvent infinis!).
Prolog prend en charge de nombreuses fonctionnalités "extra-logiques" ou "non logiques", y compris la coupe assert
et la retract
projection de variables pour l'arithmétique en utilisantis
, et ainsi de suite. Beaucoup de ces fonctionnalités facilitent l'expression de flux de contrôle complexes et la manipulation de la base de données globale de faits de Prolog. Une caractéristique très intéressante de Prolog est que le code Prolog est lui-même stocké dans la base de données globale des faits et peut être interrogé au moment de l'exécution. Cela rend facile d'écrire des méta-interprètes qui modifient le comportement du code Prolog en cours d'interprétation. Par exemple, il est possible d'encoder la recherche en largeur d'abord dans Prolog à l'aide d'un méta-interpréteur qui change l'ordre de recherche. C'est une technique extrêmement puissante qui n'est pas bien connue en dehors du monde Prolog. «The Art of Prolog» décrit cette technique en détail.
D'énormes efforts ont été déployés pour améliorer les implémentations de Prolog, dont la plupart sont basées sur la Warren Abstract Machine (WAM). Le WAM utilise un modèle à effets secondaires dans lequel des valeurs sont affectées de manière destructive à des variables logiques, ces effets secondaires étant annulés lors du retour en arrière. De nombreuses fonctionnalités peuvent être ajoutées à Prolog en étendant les instructions du WAM. Un inconvénient de cette approche est que les documents d'implémentation Prolog peuvent être difficiles à lire sans une solide compréhension du WAM. D'autre part, les implémenteurs de Prolog ont un modèle commun pour discuter des problèmes d'implémentation. De nombreuses recherches ont été menées en parallèle avec Prolog, aboutissant à Andorra Prolog dans les années 1990. Au moins certaines de ces idées se perpétuent dans Ciao Prolog. (Ciao Prolog regorge d'idées intéressantes, dont beaucoup vont bien au-delà du standard Prolog.)
Prolog a une belle syntaxe de style "pattern-matching" basée sur l'unification qui donne des programmes très succincts. Les prologues aiment leur syntaxe, tout comme les lispers aiment leurs s-expressions. Prolog dispose également d'une grande bibliothèque de prédicats standard. En raison de toute l'ingénierie nécessaire pour rendre le WAM rapide, il existe des implémentations Prolog très performantes et matures. En conséquence, de nombreux grands systèmes basés sur la connaissance ont été entièrement écrits en Prolog.
miniKanren a été conçu comme un langage de programmation logique minimal, avec une implémentation petite, facilement compréhensible et facilement piratable. miniKanren était à l'origine intégré à Scheme et a été porté dans des dizaines d'autres langues hôtes au cours de la dernière décennie. L'implémentation miniKanren la plus populaire est 'core.logic' dans Clojure, qui a maintenant de nombreuses extensions de type Prolog et un certain nombre d'optimisations. Récemment, le cœur de l'implémentation de miniKanren a été encore plus simplifié, résultant en un minuscule «micro noyau» appelé «microKanren». miniKanren peut alors être implémenté sur ce noyau microKanren. Le portage de microKanren ou miniKanren vers une nouvelle langue hôte est devenu un exercice standard pour les programmeurs qui apprennent miniKanren. Par conséquent,
Les implémentations standard de miniKanren et microKanren ne contiennent aucune mutation ou autres effets secondaires, à une seule exception: certaines versions de miniKanren utilisent l'égalité de pointeur pour la comparaison des variables logiques. Je considère cela comme un «effet bénin», bien que de nombreuses implémentations évitent même cet effet en passant un compteur à travers l'implémentation. Il n'y a pas non plus de base de données mondiale de faits. La philosophie d'implémentation de miniKanren est inspirée de la programmation fonctionnelle: les mutations et les effets doivent être évités, et toutes les constructions de langage doivent respecter la portée lexicale. Si vous regardez attentivement la mise en œuvre, vous pourriez même apercevoir quelques monades. L'implémentation de la recherche est basée sur la combinaison et la manipulation de flux paresseux, encore une fois sans utiliser de mutation. Ces choix d'implémentation conduisent à des compromis très différents de ceux de Prolog. Dans Prolog, la recherche de variables est en temps constant, mais le retour en arrière nécessite l'annulation des effets secondaires. Dans miniKanren, la recherche de variables est plus coûteuse, mais le retour en arrière est «gratuit». En fait, il n'y a pas de retour en arrière dans miniKanren, en raison de la façon dont les flux sont gérés.
Un aspect intéressant de l'implémentation miniKanren est que le code est intrinsèquement thread-safe et - au moins en théorie - trivialement parallélisable. Bien sûr, paralléliser le code sans le ralentir n'est pas anodin, étant donné que chaque thread ou processus doit avoir suffisamment de travail pour compenser la surcharge de la parallélisation. Pourtant, c'est un domaine de la mise en œuvre de miniKanren qui, je l'espère, recevra plus d'attention et d'expérimentation.
miniKanren utilise la vérification d'occurrence pour l'unification et utilise une recherche entrelacée complète au lieu d'une recherche en profondeur d'abord. La recherche entrelacée utilise plus de mémoire que la recherche en profondeur, mais peut trouver des réponses dans certains cas où la recherche en profondeur diverge / boucle pour toujours. miniKanren ne soutenir quelques opérateurs extra-logiques --- conda
, condu
et project
, par exemple. conda
et condu
peut être utilisé pour simuler la coupe de Prolog, et project
peut être utilisé pour obtenir la valeur associée à une variable logique.
La présence de conda
, condu
etproject
--- et la possibilité de modifier facilement la stratégie de recherche --- permet aux programmeurs d'utiliser miniKanren comme un langage de type Prolog intégré. Cela est particulièrement vrai pour les utilisateurs de 'core.logic' de Clojure, qui comprend de nombreuses extensions de type Prolog. Cette utilisation «pragmatique» de miniKanren semble représenter la majorité de l'utilisation de miniKanren dans l'industrie. Les programmeurs qui souhaitent ajouter un système de raisonnement basé sur la connaissance à une application existante écrite en Clojure ou Python ou JavaScript ne sont généralement pas intéressés par la réécriture de l'ensemble de leur application dans Prolog. L'intégration d'un petit langage de programmation logique dans Clojure ou Python est beaucoup plus attrayante. Une implémentation Prolog intégrée fonctionnerait tout aussi bien à cette fin, vraisemblablement.
En plus de l'utilisation de miniKanren comme langage de programmation logique embarqué pragmatique similaire dans l'esprit de Prolog, miniKanren est utilisé pour la recherche en programmation «relationnelle». Autrement dit, en écrivant des programmes qui se comportent comme des relations mathématiques plutôt que comme des fonctions mathématiques. Par exemple, dans Scheme, la append
fonction peut ajouter deux listes, renvoyant une nouvelle liste: l'appel de fonction (append '(a b c) '(d e))
renvoie la liste (a b c d e)
. Nous pouvons cependant également traiter append
comme une relation à trois places plutôt que comme une fonction à deux arguments. L'appel (appendo '(a b c) '(d e) Z)
associerait alors la variable logique Z
à la liste (a b c d e)
. Bien sûr, les choses deviennent plus intéressantes lorsque nous plaçons des variables logiques dans d'autres positions. L'appel (appendo X '(d e) '(a b c d e))
s'associe X
avec (a b c)
, tandis que l'appel(appendo X Y '(a b c d e))
associés X
et Y
avec des paires de listes qui, une fois ajoutées, sont égales à (a b c d e)
. Par exemple X
= (a b)
et Y
= (c d e)
sont une de ces paires de valeurs. On peut aussi écrire (appendo X Y Z)
, qui produira une infinité de triplets de listes X
, Y
et de Z
telle sorte que annexant X
à Y
produit Z
.
Cette version relationnelle de append
peut être facilement exprimée dans Prolog, et est en fait montrée dans de nombreux tutoriels Prolog. En pratique, les programmes Prolog plus complexes ont tendance à utiliser au moins quelques fonctionnalités extra-logiques, telles que couper, qui empêchent de traiter le programme résultant comme une relation. En revanche, miniKanren est explicitement conçu pour prendre en charge ce style de programmation relationnelle. Des versions plus récentes de miniKanren ont le soutien à la résolution de contrainte symbolique ( symbolo
, numbero
,absento
, contraintes de diségalité, programmation logique nominale) pour faciliter l'écriture de programmes non triviaux sous forme de relations. En pratique, je n'utilise jamais aucune des fonctionnalités extra-logiques de miniKanren, et j'écris tous mes programmes miniKanren sous forme de relations. Les programmes relationnels les plus intéressants sont les interprètes relationnels pour un sous-ensemble de Scheme. Ces interprètes ont de nombreuses capacités intéressantes, telles que la génération d'un million de programmes Scheme qui évaluent à la liste (I love you)
, ou la génération triviale de quines (programmes qui s'évaluent eux-mêmes).
miniKanren fait un certain nombre de compromis pour permettre ce style de programmation relationnel, qui sont très différents des compromis que Prolog fait. Au fil du temps, miniKanren a ajouté plus de contraintes symboliques, devenant vraiment un langage de programmation de logique de contrainte orienté symboliquement. Dans de nombreux cas, ces contraintes symboliques permettent d'éviter d'utiliser des opérateurs extra-logiques comme condu
et project
. Dans d'autres cas, ces contraintes symboliques ne sont pas suffisantes. Un meilleur support des contraintes symboliques est un domaine actif de la recherche miniKanren, avec la question plus large de la manière d'écrire des programmes plus grands et plus complexes sous forme de relations.
En bref, miniKanren et Prolog ont des fonctionnalités, des implémentations et des utilisations intéressantes, et je pense que cela vaut la peine d'apprendre les idées des deux langues. Il existe également d'autres langages de programmation logique très intéressants, tels que Mercury, Curry et Gödel, chacun ayant sa propre vision de la programmation logique.
Je terminerai par quelques ressources miniKanren:
Le site Web principal de miniKanren:
http://minikanren.org/
Une interview que j'ai donnée sur la programmation relationnelle et miniKanren, y compris une comparaison avec Prolog:
http://www.infoq.com/interviews/byrd-relational-programming-minikanren
À votre santé,
--Volonté