En gros, avec une logique profondément intégrée, vous (1) définissez un type de données représentant la syntaxe de votre logique, (2) donnez un modèle de la syntaxe et (3) prouvez que les axiomes de votre syntaxe sont sains avec respect au modèle. Avec une incorporation peu profonde, vous sautez les étapes (1) et (2), commencez simplement par un modèle et prouvez les incohérences entre les formules. Cela signifie que les enfoncements peu profonds demandent généralement moins de travail, car ils représentent un travail que vous finirez généralement par faire avec une incrustation profonde.
Cependant, si vous avez une intégration profonde, il est généralement plus facile d’écrire des procédures de décision réfléchies, car vous travaillez avec des formules qui ont une syntaxe sur laquelle vous pouvez revenir. De plus, si votre modèle est étrange ou compliqué, vous ne souhaitez généralement pas travailler directement avec la sémantique. (Par exemple, si vous utilisez la biorthogonalité pour forcer la fermeture admissible ou les modèles de style Kripke pour forcer les propriétés du cadre dans les logiques de séparation, ou des jeux similaires.) , qui remplira votre cœur de rage, puisque c’est (a) trivial, et (b) une source ininterrompue de contrariété.
La bonne séquence à suivre est la suivante: (1) essayez de vous en servir avec une imbrication peu profonde. (2) Lorsque cela s'essouffle, essayez d'utiliser des tactiques et des devis pour exécuter les procédures de décision que vous souhaitez exécuter. (3) Si cela s'essouffle également, abandonnez et utilisez une syntaxe typée de manière dépendante pour votre intégration profonde.
- Prévoyez de prendre quelques mois (3) s'il s'agit de votre première sortie. Vous aurez besoin de se familiariser avec la fantaisie fonctionnalités de votre assistant preuve rester sain d' esprit. (Mais c'est un investissement qui rapportera en général.)
- Si votre assistant de preuve n'a pas de types dépendants, restez au niveau 2.
- Si votre langage objet est lui-même dactylographié, restez au niveau 2.
Aussi, n'essayez pas de monter graduellement dans l'échelle. Lorsque vous décidez de gravir les échelons de la complexité, faites un pas complet à la fois. Si vous faites les choses petit à petit, vous obtiendrez un grand nombre de théorèmes étranges et inutilisables (par exemple, vous obtiendrez plusieurs syntaxes à moitié assondues et des théorèmes qui mélangent la syntaxe et la sémantique de façon étrange), ce que vous obtiendrez. finalement avoir à jeter.
EDIT: Voici un commentaire expliquant pourquoi il est si tentant de gravir progressivement les échelons et pourquoi cela conduit (en général) à la souffrance.
Concrètement, supposons que vous avez un peu profonde intégration de la logique de séparation, avec les conjonctions et unité . Ensuite, vous allez prouver des théorèmes du type et , etc. Maintenant, lorsque vous essayez réellement d’utiliser la logique pour prouver que le programme est correct, vous finirez par avoir quelque chose comme et vous voudrez en fait quelque chose comme .A⋆BIA⋆B⟺B⋆A(A⋆B)⋆C⟺A⋆(B⋆C)(I⋆A)⋆(B⋆C)A⋆(B⋆(C⋆I))
À ce stade, vous serez ennuyé de devoir réassocier manuellement des formules et vous penserez: "Je sais! Je vais interpréter un type de données de listes comme une liste de formules séparées. Ainsi, je peux interpréter comme concaténation de ces listes, puis les formules ci-dessus seront égales par définition! "⋆
C'est vrai et ça marche! Cependant, notez que la conjonction est également ACUI, de même que la disjonction. Donc, vous allez suivre le même processus dans d'autres preuves, avec différents types de données de liste, puis vous aurez trois syntaxes pour différents fragments de la logique de séparation, et vous aurez des métathéorèmes pour chacun d'eux, qui seront inévitablement différents, et vous vous retrouverez à vouloir un métathéorème que vous avez prouvé pour séparer la conjonction de la disjonction, puis vous aurez envie de mélanger les syntaxes, puis vous deviendrez fou.
Il est préférable de cibler le plus gros fragment que vous pouvez manipuler avec un effort raisonnable, et de le faire.
Il est important de comprendre qu'il existe un spectre allant du plus profond au moins profond. Vous modélisez profondément les parties de votre langage qui devraient en quelque sorte participer à un argument inductif au sujet de sa construction, il est préférable de laisser le reste dans la vue superficielle de la sémantique directe du substrat de la logique.
Par exemple, lorsque vous voulez raisonner sur Hoare Logic, vous pouvez modéliser le langage d'expression de manière superficielle, mais le contour du langage assign-if-while doit être un type de données concret. Vous n'avez pas besoin d'entrer la structure de x + y ou a <b, mais vous devez travailler avec
while
etc.Dans les autres réponses, il y avait des allusions à des types dépendants. Cela rappelle le problème ancien de représenter les langues avec des classeurs de manière saine, de manière à ce qu'elles soient aussi superficielles que possible, tout en admettant certains arguments inductifs. Mon impression est que le jury est toujours en train de juger de toutes les approches et communications différentes qui ont émergé au cours des 10-20 dernières années sur ce sujet. Le "défi POPLmark" pour les différentes communautés d'assistants de preuve était également à ce sujet dans une certaine mesure.
Bizarrement, dans HOL classique sans types dépendants, l’approche HOL-Nominal de C. Urban fonctionnait assez bien pour la reliure superficielle, bien qu’elle ne tienne pas compte des changements culturels dans ces communautés de la formalisation du langage de programmation.
la source